package main
//原来的环境变量
//set GOARCH=amd64 
//set GOOS=windows
//新的环境变量
//set GOARCH=wasm 
//set GOOS=js 
//set CGO_ENABLED=0
//go build -o lib.wasm facecat-wasm.go
//go run server.go
//http://127.0.0.1:8087
//应使用tinygo来编译
 
import (
    "fmt"
    "math"
    "strconv"
    "strings"
    "time"
    "sort"
    "encoding/xml"
    "syscall/js"
)

/*
* 坐标结构
*/
type FCPoint struct {
   X float64 //横坐标
   Y float64 //纵坐标
   IsNotEmpty bool //是否不为空
}

func CreatePoint(dx float64, dy float64) FCPoint{
	point := FCPoint{X:dx, Y:dy}
    point.IsNotEmpty = true
    return point
}

/*
* 大小结构
*/
type FCSize struct {
   Cx float64 //长
   Cy float64 //宽
   IsNotEmpty bool //是否不为空
}

func CreateSize(dcx float64, dcy float64) FCSize{
	size := FCSize{Cx:dcx, Cy:dcy}
    size.IsNotEmpty = true
    return size
}

/*
* 矩形结构
*/
type FCRect struct {
   Left float64 //左侧
   Top float64 //上侧
   Right float64 //右侧
   Bottom float64 //底部
   IsNotEmpty bool //是否不为空
}

func CreateRect(dleft float64, dtop float64, dright float64, dbottom float64) FCRect{
    rect := FCRect{Left:dleft, Top:dtop, Right:dright, Bottom:dbottom}
    rect.IsNotEmpty = true
	return rect
}

/*
* 边距信息
*/
type FCPadding struct {
   Left float64 //左侧
   Top float64 //上侧
   Right float64 //右侧
   Bottom float64 //底部
   IsNotEmpty bool //是否不为空
}

func CreatePadding(dleft float64, dtop float64, dright float64, dbottom float64) FCPadding{
	padding := FCPadding{Left:dleft, Top:dtop, Right:dright, Bottom:dbottom}
    padding.IsNotEmpty = true
    return padding
}

//字符串转换成float64
func ConvertToFloat64(str string)float64{
    if len(str) > 0{
	    floatvar, _ := strconv.ParseFloat(str, 64)
	    return floatvar
    }else{
        return 0
    }
}

//字符串转换成int
func ConvertToInt(str string)int{
	intvar, _ := strconv.ParseInt(str, 10, 32)
	return int(intvar)
}

//字符串转换成int
func ConvertToInt64(str string)int64{
	intvar, _ := strconv.ParseInt(str, 10, 64)
	return int64(intvar)
}

/*
* float64转换成字符串
*/
func ConvertFloat64ToStr(value float64)(string){
    return fmt.Sprintf("%f", value)
}

/*
* int转换成字符串
*/
func ConvertIntToStr(value int)(string){
    return strconv.Itoa(value)
}

/*
* 转换颜色
*/
func ConvertToColor(str string)(string){
    if strings.Contains(str, "rgba("){
        newStr := strings.Replace(str, "rgba(", "", -1)
        newStr = strings.Replace(newStr, ")", "", -1)
        strs := strings.Split(newStr, ",")
        a := ConvertToFloat64(strs[3]) / 255
        newStr = "rgba(" + strs[0] + "," + strs[1] + "," + strs[2] + "," + ConvertFloat64ToStr(a) + ")"
        return newStr
    }else{
        return str
    }
}

type ClickGridCellEventCallBack func(grid *FCView, row *FCGridRow, gridColumn *FCGridColumn, cell *FCGridCell, firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint, clicks int)
type ClickGridColumnEventCallBack func(grid *FCView, gridColumn *FCGridColumn, firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint, clicks int)
type ClickTreeNodeEventCallBack func(tree *FCView, node *FCTreeNode, firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint, clicks int)
type CalculateChartMaxMinEventCallBack func(chart *FCView)
type InvalidateViewEventCallBack func(view *FCView)
type InvalidateEventCallBack func(paint *FCPaint)
type KeyEventCallBack func(view *FCView, key int)
type MouseEventCallBack func(view *FCView, mp FCPoint, buttons int, clicks int, delta int)
type ClickEventCallBack func(view *FCView, firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint, clicks int)
type PaintEventCallBack func(view *FCView, paint *FCPaint, clipRect FCRect)
type PaintGridCellEventCallBack func(grid *FCView, row *FCGridRow, column *FCGridColumn, cell *FCGridCell, paint *FCPaint, left float64, top float64, right float64, bottom float64)
type PaintGridColumnEventCallBack func(grid *FCView, column *FCGridColumn, paint *FCPaint, left float64, top float64, right float64, bottom float64)
type PaintTreeNodeEventCallBack func(tree *FCView, row *FCTreeRow, column *FCTreeColumn, node *FCTreeNode, paint *FCPaint, left float64, top float64, right float64, bottom float64)
type PaintCalendarDayButtonEventCallBack func(calendar *FCView, dayButton *DayButton, paint *FCPaint)
type PaintCalendarMonthButtonEventCallBack func(calendar *FCView, monthButton *MonthButton, paint *FCPaint)
type PaintCalendarYearButtonEventCallBack func(calendar *FCView, yearButton *YearButton, paint *FCPaint)
type PaintCalendarHeadDivEventCallBack func(calendar *FCView, headDiv *HeadDiv, paint *FCPaint)
type RenderViewsEventCallBack func(views []*FCView, paint *FCPaint, clipRect FCRect)
type TouchEventCallBack func(view *FCView, firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint)
type UpdateViewEventCallBack func(views []*FCView)
type ContainsPointCallBack func(view *FCView, mp FCPoint)(bool)
/*
* 绘图结构
*/
type FCPaint struct{
    OnCalculateChartMaxMin CalculateChartMaxMinEventCallBack
    OnClick ClickEventCallBack
    OnClickGridCell ClickGridCellEventCallBack
    OnClickGridColumn ClickGridColumnEventCallBack
    OnClickTreeNode ClickTreeNodeEventCallBack
    OnContainsPoint ContainsPointCallBack
    OnInvalidateView InvalidateViewEventCallBack
    OnInvalidate InvalidateEventCallBack
    OnKeyDown KeyEventCallBack
    OnKeyUp KeyEventCallBack
    OnMouseDown MouseEventCallBack
    OnMouseMove MouseEventCallBack
    OnMouseUp MouseEventCallBack
    OnMouseWheel MouseEventCallBack
    OnMouseEnter MouseEventCallBack
    OnMouseLeave MouseEventCallBack
    OnPaint PaintEventCallBack
    OnPaintBorder PaintEventCallBack
    OnPaintCalendarDayButton PaintCalendarDayButtonEventCallBack
    OnPaintCalendarMonthButton PaintCalendarMonthButtonEventCallBack
    OnPaintCalendarYearButton PaintCalendarYearButtonEventCallBack
    OnPaintCalendarHeadDiv PaintCalendarHeadDivEventCallBack
    OnPaintChartScale PaintEventCallBack
    OnPaintChartHScale PaintEventCallBack
    OnPaintChartStock PaintEventCallBack
    OnPaintChartPlot PaintEventCallBack
    OnPaintChartCrossLine PaintEventCallBack
    OnPaintGridCell PaintGridCellEventCallBack
    OnPaintGridColumn PaintGridColumnEventCallBack
    OnPaintTreeNode PaintTreeNodeEventCallBack
    OnRenderViews RenderViewsEventCallBack
    OnTouchBegin TouchEventCallBack 
    OnTouchMove TouchEventCallBack 
    OnTouchEnd TouchEventCallBack 
    OnUpdateView UpdateViewEventCallBack 
    CancelClick bool //是否退出点击
    DefaultUIStyle string //默认样式
    DragBeginPoint FCPoint //拖动开始时的触摸位置
    DragBeginRect FCRect //拖动开始时的区域
    DraggingView []*FCView  //正被拖动的控件
    FirstTouch bool //是否第一次触摸
    FocusedView []*FCView //焦点视图
    IsDoubleClick bool
    IsMobile bool //是否移动端
    IsNotEmpty bool //是否不为空
    LastClickTime int64 //上次点击的时间
    ResizeColumnState int //改变列宽度的状态
    ResizeColumnBeginWidth float64 //改变列宽度的起始值
    ResizeColumnIndex int //改变列宽度的索引
    ScaleFactorX float64 //横向缩放比例
    ScaleFactorY float64 //纵向缩放比例
    SecondTouch bool //是否第二次触摸
    Size FCSize //尺寸
    SystemFont string
    TouchDownPoint FCPoint //鼠标按下时的坐标
    TouchDownView []*FCView //鼠标按下的视图
    TouchMoveView []*FCView//鼠标移动的视图
    TouchFirstPoint FCPoint //第一次触摸的点
    TouchSecondPoint FCPoint //第二次触摸的点
    Views []*FCView //子视图
    Canvas js.Value //Canvas
    Context js.Value //Context
    OffsetX float64 //横向偏移
    OffsetY float64 //纵向便宜
    Ratio float64 //缩放比例
}

/*
* 初始化
*/
func CreatePaint()(*FCPaint){
    paint := new(FCPaint)
    paint.IsNotEmpty = true
    paint.ScaleFactorX = 1
    paint.ScaleFactorY = 1
    paint.ResizeColumnIndex = -1
    paint.SystemFont = "Segoe UI"
    paint.DefaultUIStyle = "light"
    paint.Ratio = 1
    return paint
}

func (c *FCPaint)GetTouchDownView()(*FCView){
    length := len(c.TouchDownView)
    if length > 0{
        return c.TouchDownView[0]
    }else{
        noneView :=new(FCView)
        noneView.IsNotEmpty = false
        return noneView
    }
}

func (c *FCPaint)SetTouchDownView(view *FCView){
    var pList []*FCView
    c.TouchDownView = pList
    c.TouchDownView = append(c.TouchDownView, view)
}

func (c *FCPaint)GetTouchMoveView()(*FCView){
    length := len(c.TouchMoveView)
    if length > 0{
        return c.TouchMoveView[0]
    }else{
        noneView := new(FCView)
        noneView.IsNotEmpty = false
        return noneView
    }
}

func (c *FCPaint)SetTouchMoveView(view *FCView){
    var pList []*FCView
    c.TouchMoveView = pList
    c.TouchMoveView = append(c.TouchMoveView, view)
}

func (c *FCPaint)GetFocusedView()(*FCView){
    length := len(c.FocusedView)
    if length > 0{
        return c.FocusedView[0]
    }else{
        noneView := new(FCView)
        noneView.IsNotEmpty = false
        return noneView
    }
}

func (c *FCPaint)SetFocusedView(view *FCView){
    var pList []*FCView
    c.FocusedView = pList
    c.FocusedView = append(c.FocusedView, view)
}

func (c *FCPaint)GetDraggingView()(*FCView){
    length := len(c.DraggingView)
    if length > 0{
        return c.DraggingView[0]
    }else{
        noneView := new(FCView)
        noneView.IsNotEmpty = false
        return noneView
    }
}

func (c *FCPaint)SetDraggingView(view *FCView){
    var pList []*FCView
    c.DraggingView = pList
    c.DraggingView = append(c.DraggingView, view)
}

 /*
* 开始绘图
* rect:区域
*/
func (c *FCPaint)BeginPaint(rect FCRect, pRect FCRect){
    c.OffsetX = 0
    c.OffsetY = 0
}
/*
* 绘制线
* color:颜色
* width:宽度
* style:样式
* x1:横坐标1
* y1:纵坐标1
* x2:横坐标2
* y2:纵坐标2
*/
func (c *FCPaint)DrawLine(color string, width float64, style float64, x1 float64, y1 float64, x2 float64, y2 float64){
    c.Context.Call("beginPath")
    c.Context.Set("strokeStyle", ConvertToColor(color))
    c.Context.Set("lineWidth", math.Min(c.ScaleFactorX, c.ScaleFactorY) * width)
    c.Context.Call("moveTo", (x1 + c.OffsetX) * c.ScaleFactorX, (y1 + c.OffsetY) * c.ScaleFactorY)
    c.Context.Call("lineTo", (x2 + c.OffsetX) * c.ScaleFactorX, (y2 + c.OffsetY) * c.ScaleFactorY)
    c.Context.Call("stroke")
}
/*
*绘制连续线
*color:颜色 
*width:宽度 
*style:样式 
*/
func (c *FCPaint)DrawPolyline(color string, width float64, style float64, apt []FCPoint){
    c.Context.Call("beginPath")
    c.Context.Set("strokeStyle", ConvertToColor(color))
    c.Context.Set("lineWidth", math.Min(c.ScaleFactorX, c.ScaleFactorY) * width)
    for i := 0; i < len(apt); i++ {
        x := (apt[i].X + c.OffsetX) * c.ScaleFactorX
        y := (apt[i].Y + c.OffsetY) * c.ScaleFactorY
        if i == 0{
            c.Context.Call("moveTo", x, y)
        }else{
            c.Context.Call("lineTo", x, y)
        }
    }
    c.Context.Call("stroke")
}
/*
*绘制多边形
*color:颜色 
*width:宽度 
*style:样式 
*/
func (c *FCPaint)DrawPolygon(color string, width float64, style float64, apt []FCPoint){
    c.Context.Call("beginPath")
    c.Context.Set("strokeStyle", ConvertToColor(color))
    c.Context.Set("lineWidth", math.Min(c.ScaleFactorX, c.ScaleFactorY) * width)
    for i := 0; i < len(apt); i++ {
        x := (apt[i].X + c.OffsetX) * c.ScaleFactorX
        y := (apt[i].Y + c.OffsetY) * c.ScaleFactorY
        if i == 0{
            c.Context.Call("moveTo", x, y)
        }else{
            c.Context.Call("lineTo", x, y)
        }
    }
    c.Context.Call("closePath")
    c.Context.Call("stroke")
}
/*
* 绘制矩形
* color:颜色
* width:宽度
* style:样式
* left:左侧坐标
* top:上方坐标
* right:右侧坐标
* bottom:下方坐标
*/
func (c *FCPaint)DrawRect(color string, width float64, style float64, left float64, top float64, right float64, bottom float64){
    w := right - left
	h := bottom - top
    c.Context.Set("strokeStyle", ConvertToColor(color))
    c.Context.Set("lineWidth", math.Min(c.ScaleFactorX, c.ScaleFactorY) * width)
    c.Context.Call("strokeRect", (left + c.OffsetX) * c.ScaleFactorX, (top + c.OffsetY) * c.ScaleFactorY, w * c.ScaleFactorX, h * c.ScaleFactorY)
}
 /*
* 绘制圆角矩形
* color:颜色
* width:宽度
* style:样式
* left:左侧坐标
* top:上方坐标
* right:右侧坐标
* bottom:下方坐标
* cornerRadius:圆角
*/
func (c *FCPaint)DrawRoundRect(color string, width float64, style float64, left float64, top float64, right float64, bottom float64, cornerRadius float64){
    c.Context.Set("strokeStyle", ConvertToColor(color))
    c.Context.Set("lineWidth", math.Min(c.ScaleFactorX, c.ScaleFactorY) * width)
    if cornerRadius > 0 {
		w := (right - left) * c.ScaleFactorX
		h := (bottom - top) * c.ScaleFactorY
		x := (left + c.OffsetX) * c.ScaleFactorX
		y := (top + c.OffsetY) * c.ScaleFactorY
        corner := math.Min(c.ScaleFactorX, c.ScaleFactorY) * cornerRadius
		c.Context.Call("beginPath")
		c.Context.Call("moveTo", x + corner, y)
		c.Context.Call("arcTo", x + w, y, x + w, y + h, corner)
		c.Context.Call("arcTo", x + w, y + h, x, y + h, corner)
		c.Context.Call("arcTo", x, y + h, x, y, corner)
		c.Context.Call("arcTo", x, y, x + corner, y, corner)
        c.Context.Call("stroke")
	} else {
        w := right - left
	    h := bottom - top
		c.Context.Call("strokeRect", (left + c.OffsetX) * c.ScaleFactorX, (top + c.OffsetY) * c.ScaleFactorY, w * c.ScaleFactorX, h * c.ScaleFactorY)
	}   
}
/*
* 绘制椭圆
* color:颜色
* width:宽度
* style:样式
* left:左侧坐标
* top:上方坐标
* right:右侧坐标
* bottom:下方坐标
*/
func (c *FCPaint)DrawEllipse(color string, width float64, style float64, left float64, top float64, right float64, bottom float64){
    w := right - left
	h := bottom - top
    c.Context.Set("strokeStyle", ConvertToColor(color))
    c.Context.Set("lineWidth", math.Min(c.ScaleFactorX, c.ScaleFactorY) * width)
    centerX := (left + (right - left) / 2 + c.OffsetX) * c.ScaleFactorX
	centerY := (top + (bottom - top) / 2 + c.OffsetY) * c.ScaleFactorY
    c.Context.Call("beginPath")
    c.Context.Call("ellipse", centerX, centerY, (w / 2) * c.ScaleFactorX, (h / 2) * c.ScaleFactorY, 0, 0, math.Pi * 2)
    c.Context.Call("stroke")
}
 /*
* 绘制文字
* text:文字
* color:颜色
* font:字体
* x:横坐标
* y:纵坐标
*/
func (c *FCPaint)DrawText(text string, color string, font string, x float64, y float64){
    if len(text) > 0 && len(font) > 0{
        strs := strings.Split(font, ",")
        fontFamily := strs[0]
		if fontFamily == "Default" {
			fontFamily = c.SystemFont
        }
		sFont := ConvertFloat64ToStr(math.Floor(ConvertToFloat64(strs[1]))) + "px " + fontFamily
        if c.ScaleFactorX != 1 || c.ScaleFactorY != 1 {
            newSize := (c.ScaleFactorX + c.ScaleFactorY) / 2.0 * ConvertToFloat64(strs[1])
            sFont = ConvertFloat64ToStr(math.Floor(newSize)) + "px " + fontFamily
		}
        for i := 2; i < len(strs); i++ {
			iStr := strings.ToLower(strs[i]);
			if (iStr == "bold" || iStr == "italic") {
				sFont = iStr + " " + sFont;
			}
		}
        c.Context.Set("font", sFont)
        c.Context.Set("fillStyle", ConvertToColor(color))
        c.Context.Set("textAlign", "left")
        c.Context.Set("textBaseline", "top")
        c.Context.Call("fillText", text, (x + c.OffsetX) * c.ScaleFactorX, (y + c.OffsetY) * c.ScaleFactorY)
    }
}
/*
* 结束绘图
*/
func (c *FCPaint)EndPaint(){
}
/*
*绘制多边形
*color:颜色 
*apt:坐标
*/
func (c *FCPaint)FillPolygon(color string, apt []FCPoint){		
    c.Context.Call("beginPath")
    c.Context.Set("fillStyle", ConvertToColor(color))
    for i := 0; i < len(apt); i++ {
        x := (apt[i].X + c.OffsetX) * c.ScaleFactorX
        y := (apt[i].Y + c.OffsetY) * c.ScaleFactorY
        if i == 0{
            c.Context.Call("moveTo", x, y)
        }else{
            c.Context.Call("lineTo", x, y)
        }
    }
    c.Context.Call("closePath")
    c.Context.Call("fill")
}
/*
* 填充矩形
* color:颜色
* left:左侧坐标
* top:上方坐标
* right:右侧坐标
* bottom:下方坐标
*/
func (c *FCPaint)FillRect(color string, left float64, top float64, right float64, bottom float64){
    w := right - left
	h := bottom - top
    c.Context.Set("fillStyle", ConvertToColor(color))
    c.Context.Call("fillRect", (left + c.OffsetX) * c.ScaleFactorX, (top + c.OffsetY) * c.ScaleFactorY, w * c.ScaleFactorX, h * c.ScaleFactorY)
}
/*
* 填充圆角矩形
* color:颜色
* left:左侧坐标
* top:上方坐标
* right:右侧坐标
* bottom:下方坐标
* cornerRadius:圆角
*/
func (c *FCPaint)FillRoundRect(color string, left float64, top float64, right float64, bottom float64, cornerRadius float64){
    c.Context.Set("fillStyle", ConvertToColor(color))
    if cornerRadius > 0 {
		w := (right - left) * c.ScaleFactorX
		h := (bottom - top) * c.ScaleFactorY
		x := (left + c.OffsetX) * c.ScaleFactorX
		y := (top + c.OffsetY) * c.ScaleFactorY
        corner := math.Min(c.ScaleFactorX, c.ScaleFactorY) * cornerRadius
		c.Context.Call("beginPath")
		c.Context.Call("moveTo", x + corner, y)
		c.Context.Call("arcTo", x + w, y, x + w, y + h, corner)
		c.Context.Call("arcTo", x + w, y + h, x, y + h, corner)
		c.Context.Call("arcTo", x, y + h, x, y, corner)
		c.Context.Call("arcTo", x, y, x + corner, y, corner)
        c.Context.Call("fill")
	} else {
        w := right - left
	    h := bottom - top
		c.Context.Call("fillRect", (left + c.OffsetX) * c.ScaleFactorX, (top + c.OffsetY) * c.ScaleFactorY, w * c.ScaleFactorX, h * c.ScaleFactorY)
	}   
}
/*
* 填充椭圆
* color:颜色
* left:左侧坐标
* top:上方坐标
* right:右侧坐标
* bottom:下方坐标
*/
func (c *FCPaint)FillEllipse(color string, left float64, top float64, right float64, bottom float64){
    w := right - left
	h := bottom - top
    c.Context.Set("fillStyle", ConvertToColor(color))
    centerX := (left + (right - left) / 2 + c.OffsetX) * c.ScaleFactorX
	centerY := (top + (bottom - top) / 2 + c.OffsetY) * c.ScaleFactorY
    c.Context.Call("beginPath")
    c.Context.Call("ellipse", centerX, centerY, (w / 2) * c.ScaleFactorX, (h / 2) * c.ScaleFactorY, 0, 0, math.Pi * 2)
    c.Context.Call("fill")
}
/*
* 裁剪
* left:左侧坐标
* top:上方坐标
* right:右侧坐标
* bottom:下方坐标
*/
func (c *FCPaint)SetClip(left float64, top float64, right float64, bottom float64){
    w := right - left
	h := bottom - top
    c.Context.Call("beginPath")
    c.Context.Call("rect", (left + c.OffsetX) * c.ScaleFactorX, (top + c.OffsetY) * c.ScaleFactorY, w * c.ScaleFactorX, h * c.ScaleFactorY)
    c.Context.Call("clip")
}
/*
* 设置偏移量
* offsetX:横向偏移
* offsetY:纵向偏移
*/
func (c *FCPaint)SetOffset(x float64, y float64){
    c.OffsetX = x
	c.OffsetY = y
}
/*
* 获取字体大小
* text:文字
* font:字体
*/
func (c *FCPaint)TextSize(text string, font string)(FCSize){
    if len(text) > 0 && len(font) > 0{
        strs := strings.Split(font, ",")
        fontFamily := strs[0]
		if fontFamily == "Default" {
			fontFamily = c.SystemFont
        }
        rate := (c.ScaleFactorX + c.ScaleFactorY) / 2.0
		sFont := ConvertFloat64ToStr(math.Floor(ConvertToFloat64(strs[1]) * rate)) + "px " + fontFamily
        for i := 2; i < len(strs); i++ {
			iStr := strings.ToLower(strs[i])
			if (iStr == "bold" || iStr == "italic") {
				sFont = iStr + " " + sFont
			}
		}
        c.Context.Set("font", sFont)
        c.Context.Set("textAlign", "left")
        c.Context.Set("textBaseline", "top")
        metrics := c.Context.Call("measureText", text)
        actualHeight := float64(metrics.Get("actualBoundingBoxAscent").Int()) + float64(metrics.Get("actualBoundingBoxDescent").Int())
        if actualHeight <= 0{
            return CreateSize(float64(metrics.Get("width").Int()) / rate, ConvertToFloat64(strs[1]) / rate)
        }else{
            tSize := CreateSize(float64(metrics.Get("width").Int()) / rate, actualHeight / rate)
            return tSize
        }
    }else{
        return CreateSize(100, 20)
    }
}
/*
* 绘制文字
* text:文字
* color:颜色
* font:字体
* left:左侧坐标
* top:上方坐标
* right:右侧坐标
* bottom:下方坐标
*/
func (c *FCPaint)DrawTextAutoEllipsis(text string, color string, font string, left float64, top float64, right float64, bottom float64){
    if len(text) != 0 {
		tSize := c.TextSize(text, font)
		if (tSize.Cx < right - left) {
			c.DrawText(text, color, font, left, top)
		} else {
			if tSize.Cx > 0 {
				subLen := 3
				for {
					newLen := len(text) - subLen
					if (newLen > 0) {
						newText := text[0:newLen] + "..."
						tSize = c.TextSize(newText, font)
						if tSize.Cx < right - left {
							c.DrawText(newText, color, font, left, top)
							break
						} else {
							subLen += 3
						}
					} else {
						break
					}
				}
			}
		}
	}
}
/*
* 保存状态
*/
func (c *FCPaint)Save(){
    c.Context.Call("save")
}
/*
* 恢复状态
*/
func (c *FCPaint)Restore(){
    c.Context.Call("restore")
}

/*
* 扩展接口
*/
type FCObject interface{
}

/*
* 基础视图
*/
type FCView struct {
    AllowDrag bool //是否允许拖动
    AllowResize bool //是否可以拖动改变大小
	Align string //横向布局
    AllowDragScroll bool //是否允许拖动滚动
    AllowPreviewsEvent bool //是否允许预处理事件
    BackColor string //背景色
    BackImage string
	BorderColor string //边线色
    BorderWidth float64 //边线宽度
    ClipRect FCRect //裁剪区域
    CornerRadius float64 //圆角
    Cursor string //光标
    DisplayOffset bool //是否显示偏移量
    Dock string //悬浮状态
    DownScrollHButton bool //是否按下横向滚动条
	DownScrollVButton bool //是否按下纵向滚动条
    Enabled bool //是否可用
    ExAttributes map[string]string
    ExView bool
    Font string //字体
    HasInput bool //是否有原生组件
    HoveredColor string //鼠标悬停时的颜色
    HoverScrollHButton bool //是否悬停横向滚动条
	HoverScrollVButton bool //是否悬停纵向滚动条
    HScrollIsVisible bool //横向滚动是否显示
    Input js.Value //原生组件
    IsNotEmpty bool //是否不为空
    Location FCPoint //坐标
    Margin FCPadding //外边距
    MaximumSize FCSize //最大大小
    Padding FCPadding //内边距
    PaintList []*FCPaint  //绘图对象
    ParentList []*FCView //父视图
    PushedColor string //鼠标按下时的颜色
    ResizePoint int //调整尺寸的点
    ScrollV float64 //纵向滚动
	ScrollH float64 //横向滚动
	ScrollSize float64 //滚动条的大小
	ShowHScrollBar bool //是否显示横向滚动条
	ShowVScrollBar bool //是否显示横向滚动条
	ScrollBarColor string //滚动条的颜色
	ScrollBarHoveredColor string //滚动条悬停的颜色
    Size FCSize //大小
    Src string
    StartScrollH float64 //开始滚动的值
	StartScrollV float64 //结束滚动的值
	StartPoint FCPoint //起始点
    StartRect FCRect //移动开始时的视图矩形
    TabIndex int //Tab索引
    TabStop bool //是否支持Tab
    Text string //文字
	TextColor string //前景色
    TopMost bool //是否置顶
    VerticalAlign string //纵向布局
	ViewName string //名称
    Views []*FCView //子视图
    ViewType string //类型
	Visible bool //可见性
    VScrollIsVisible bool //纵向滚动是否显示
    Chart []*FCChart //图表
    Calendar []*FCCalendar //日历
    SplitDiv []*FCSplitLayoutDiv //分割布局
    LayoutDiv []*FCLayoutDiv //横竖布局
    CheckBox []*FCCheckBox //复选框
    RadioButton []*FCRadioButton //单选框
    TabView []*FCTabView //多页夹
    TabPage []*FCTabPage //多页夹的页
    Menu []*FCMenu //菜单
    MenuItem []*FCMenuItem //菜单项
    ComboBox []*FCComboBox //下拉列表
    Grid []*FCGrid //表格
    Tree []*FCTree //树
    ObjectList []FCObject //扩展接口
    OnPaint PaintEventCallBack//重绘回调
    OnPaintBorder PaintEventCallBack //重绘边线回调
    OnClick ClickEventCallBack //点击方法
    OnMouseDown MouseEventCallBack  //鼠标按下
    OnMouseMove MouseEventCallBack //鼠标移动
    OnMouseWheel MouseEventCallBack //鼠标滚动
    OnMouseUp MouseEventCallBack //鼠标抬起
    OnTouchBegin TouchEventCallBack //触摸开始
    OnTouchMove TouchEventCallBack //触摸移动
    OnTouchEnd TouchEventCallBack //触摸结束
    OnKeyDown KeyEventCallBack //键盘按下
    OnKeyUp KeyEventCallBack //键盘抬起
    OnMouseEnter MouseEventCallBack
    OnMouseLeave MouseEventCallBack
}

/*
* 初始化
*/
func CreateView(viewType string)(*FCView){
    view := new(FCView)
    view.BackColor = "rgb(255,255,255)" 
    view.BorderColor = "rgb(150,150,150)" 
    view.BorderWidth = 1
    view.TextColor = "rgb(0,0,0)" 
    view.Enabled = true
    view.Visible = true 
    view.ScrollSize = 8 
    view.ScrollBarColor = "rgb(200,200,200)"
    view.ScrollBarHoveredColor = "rgb(42,138,195)"
    view.DisplayOffset = true 
    view.Dock = "none" 
    view.Font = "Default,12"
    view.HoveredColor = "none"
    view.PushedColor = "rgb(200,200,200)"
    view.Align = "left" 
    view.VerticalAlign = "top" 
    view.IsNotEmpty = true
    view.ViewType = viewType
    view.ResizePoint = -1
    view.ExAttributes = make(map[string]string)
    if viewType == "tabview"{
        tabView := CreateTabView()
        view.TabView = append(view.TabView, tabView)
    }else if viewType == "button"{
        view.HoveredColor =  "rgb(150,150,150)"
        view.PushedColor = "rgb(200,200,200)"
    }else if viewType == "label"{
        view.BorderColor = "none"
    }else if viewType == "tabpage"{
        tabPage := CreateTabPage()
        view.Visible = false
        view.TabPage = append(view.TabPage, tabPage)
    }else if viewType == "layout"{
        layout := CreateLayoutDiv()
        view.LayoutDiv = append(view.LayoutDiv, layout)
    }else if viewType == "checkbox"{
        checkBox := CreateCheckBox()
        view.CheckBox = append(view.CheckBox, checkBox)
    }else if viewType == "radiobutton"{
        radioButton := CreateRadioButton()
        view.RadioButton = append(view.RadioButton, radioButton)
    }else if viewType == "split"{
        split := CreateSplitLayoutDiv()
        view.SplitDiv = append(view.SplitDiv, split)
    }else if viewType == "grid"{
        view.ShowVScrollBar = true
        view.ShowHScrollBar = true
        grid := CreateGrid()
        view.Grid = append(view.Grid, grid)
    }else if viewType == "tree"{ 
        view.ShowVScrollBar = true
        view.ShowHScrollBar = true
        tree := CreateTree()
        view.Tree = append(view.Tree, tree)
    }else if viewType == "chart"{ 
        chart := CreateChart()
        view.Chart = append(view.Chart, chart)
    }else if viewType == "calendar"{
        calendar := CreateCalendar()
        view.Calendar = append(view.Calendar, calendar)
    }else if viewType == "menu"{
        menu := CreateMenu()
        view.MaximumSize = CreateSize(100, 300)
        view.Size = CreateSize(100, 100)
        view.ShowHScrollBar = true
        view.ShowVScrollBar = true
        view.Visible = false
        view.Menu = append(view.Menu, menu)
        layout := CreateLayoutDiv()
        view.LayoutDiv = append(view.LayoutDiv, layout)
        view.AllowPreviewsEvent = true
        layout.LayoutStyle = "toptobottom"
    }else if viewType == "menuitem"{
        menuItem := CreateMenuItem()
        view.HoveredColor =  "rgb(150,150,150)"
        view.PushedColor = "rgb(100,100,100)"
        view.Size = CreateSize(100, 25)
        view.MenuItem = append(view.MenuItem, menuItem)
    }else if viewType == "combobox"{
        comboBox := CreateComboBox()
        view.ComboBox = append(view.ComboBox, comboBox)
    }
    return view
}

func (c *FCView)GetParent()(*FCView){
    length := len(c.ParentList)
    if length > 0{
        return c.ParentList[0]
    }else{
        noneView := new(FCView)
        noneView.IsNotEmpty = false
        return noneView
    }
}

func (c *FCView)SetParent(parent *FCView){
    var pList []*FCView
    c.ParentList = pList
    c.ParentList = append(c.ParentList, parent)
}

func (c *FCView)GetPaint()(*FCPaint){
    length := len(c.PaintList)
    if length > 0{
        return c.PaintList[0]
    }else{
        nonePaint := new(FCPaint)
        nonePaint.IsNotEmpty = false
        return nonePaint
    }
}

func (c *FCView)SetPaint(paint *FCPaint){
    var pList []*FCPaint
    c.PaintList = pList
    c.PaintList = append(c.PaintList, paint)
}

func (c *FCView)GetObject()(FCObject){
    length := len(c.ObjectList)
    if length > 0{
        return c.ObjectList[0]
    }else{
        noneObject := new(FCObject)
        return noneObject
    }
}

func (c *FCView)SetObject(object FCObject){
    var pList []FCObject
    c.ObjectList = pList
    c.ObjectList = append(c.ObjectList, object)
}

func (c *FCView)GetChart()(*FCChart){
    length := len(c.Chart)
    if length > 0{
        return c.Chart[0]
    }else{
        noneChart := new(FCChart)
        noneChart.IsNotEmpty = false
        return noneChart
    }
}

func (c *FCView)SetChart(chart *FCChart){
    var pList []*FCChart
    c.Chart = pList
    c.Chart = append(c.Chart, chart)
}

func (c *FCView)GetCalendar()(*FCCalendar){
    length := len(c.Calendar)
    if length > 0{
        return c.Calendar[0]
    }else{
        noneCalendar := new(FCCalendar)
        noneCalendar.IsNotEmpty = false
        return noneCalendar
    }
}

func (c *FCView)SetCalendar(calendar *FCCalendar){
    var pList []*FCCalendar
    c.Calendar = pList
    c.Calendar = append(c.Calendar, calendar)
}

func (c *FCView)GetSplitDiv()(*FCSplitLayoutDiv){
    length := len(c.SplitDiv)
    if length > 0{
        return c.SplitDiv[0]
    }else{
        noneSplit := new(FCSplitLayoutDiv)
        noneSplit.IsNotEmpty = false
        return noneSplit
    }
}

func (c *FCView)SetSplitDiv(split *FCSplitLayoutDiv){
    var pList []*FCSplitLayoutDiv
    c.SplitDiv = pList
    c.SplitDiv = append(c.SplitDiv, split)
}

func (c *FCView)GetLayoutDiv()(*FCLayoutDiv){
    length := len(c.LayoutDiv)
    if length > 0{
        return c.LayoutDiv[0]
    }else{
        noneLayout := new(FCLayoutDiv)
        noneLayout.IsNotEmpty = false
        return noneLayout
    }
}

func (c *FCView)SetLayoutDiv(layout *FCLayoutDiv){
    var pList []*FCLayoutDiv
    c.LayoutDiv = pList
    c.LayoutDiv = append(c.LayoutDiv, layout)
}

func (c *FCView)GetCheckBox()(*FCCheckBox){
    length := len(c.CheckBox)
    if length > 0{
        return c.CheckBox[0]
    }else{
        noneCheckBox := new(FCCheckBox)
        noneCheckBox.IsNotEmpty = false
        return noneCheckBox
    }
}

func (c *FCView)SetCheckBox(checkBox *FCCheckBox){
    var pList []*FCCheckBox
    c.CheckBox = pList
    c.CheckBox = append(c.CheckBox, checkBox)
}

func (c *FCView)GetRadioButton()(*FCRadioButton){
    length := len(c.RadioButton)
    if length > 0{
        return c.RadioButton[0]
    }else{
        noneRadioButton := new(FCRadioButton)
        noneRadioButton.IsNotEmpty = false
        return noneRadioButton
    }
}

func (c *FCView)SetRadioButton(radioButton *FCRadioButton){
    var pList []*FCRadioButton
    c.RadioButton = pList
    c.RadioButton = append(c.RadioButton, radioButton)
}

func (c *FCView)GetTabPage()(*FCTabPage){
    length := len(c.TabPage)
    if length > 0{
        return c.TabPage[0]
    }else{
        noneTabPage := new(FCTabPage)
        noneTabPage.IsNotEmpty = false
        return noneTabPage
    }
}

func (c *FCView)SetTabPage(tabPage *FCTabPage){
    var pList []*FCTabPage
    c.TabPage = pList
    c.TabPage = append(c.TabPage, tabPage)
}

func (c *FCView)GetTabView()(*FCTabView){
    length := len(c.TabView)
    if length > 0{
        return c.TabView[0]
    }else{
        noneTabView := new(FCTabView)
        noneTabView.IsNotEmpty = false
        return noneTabView
    }
}

func (c *FCView)SetTabView(tabView *FCTabView){
    var pList []*FCTabView
    c.TabView = pList
    c.TabView = append(c.TabView, tabView)
}

func (c *FCView)GetMenu()(*FCMenu){
    length := len(c.Menu)
    if length > 0{
        return c.Menu[0]
    }else{
        noneMenu := new(FCMenu)
        noneMenu.IsNotEmpty = false
        return noneMenu
    }
}

func (c *FCView)SetMenu(menu *FCMenu){
    var pList []*FCMenu
    c.Menu = pList
    c.Menu = append(c.Menu, menu)
}

func (c *FCView)GetMenuItem()(*FCMenuItem){
    length := len(c.MenuItem)
    if length > 0{
        return c.MenuItem[0]
    }else{
        noneMenuItem := new(FCMenuItem)
        noneMenuItem.IsNotEmpty = false
        return noneMenuItem
    }
}

func (c *FCView)SetMenuItem(menuItem *FCMenuItem){
    var pList []*FCMenuItem
    c.MenuItem = pList
    c.MenuItem = append(c.MenuItem, menuItem)
}

func (c *FCView)GetComboBox()(*FCComboBox){
    length := len(c.ComboBox)
    if length > 0{
        return c.ComboBox[0]
    }else{
        noneComboBox := new(FCComboBox)
        noneComboBox.IsNotEmpty = false
        return noneComboBox
    }
}

func (c *FCView)SetComboBox(comboBox *FCComboBox){
    var pList []*FCComboBox
    c.ComboBox = pList
    c.ComboBox = append(c.ComboBox, comboBox)
}

func (c *FCView)GetGrid()(*FCGrid){
    length := len(c.Grid)
    if length > 0{
        return c.Grid[0]
    }else{
        noneGrid := new(FCGrid)
        noneGrid.IsNotEmpty = false
        return noneGrid
    }
}

func (c *FCView)SetGrid(grid *FCGrid){
    var pList []*FCGrid
    c.Grid = pList
    c.Grid = append(c.Grid, grid)
}

func (c *FCView)GetTree()(*FCTree){
    length := len(c.Tree)
    if length > 0{
        return c.Tree[0]
    }else{
        noneTree := new(FCTree)
        noneTree.IsNotEmpty = false
        return noneTree
    }
}

func (c *FCView)SetTree(tree *FCTree){
    var pList []*FCTree
    c.Tree = pList
    c.Tree = append(c.Tree, tree)
}

/*
* 菜单
*/
type FCMenu struct{
    AutoSize bool //是否自动适应尺寸
    ComboBox []*FCView //所在的下拉菜单
    IsNotEmpty bool
    Items []*FCView //菜单项
    Popup bool //是否弹出
}

/*
* 创建菜单
*/
func CreateMenu()(*FCMenu){
    menu := new(FCMenu)
    menu.IsNotEmpty = true
    menu.AutoSize = true
    return menu
}

/*
* 菜单项
*/
type FCMenuItem struct{
    DropDownMenu []*FCView //下拉菜单
    IsNotEmpty bool
    Items []*FCView //菜单项
    ParentMenu []*FCView //所在菜单
    ParentItem []*FCView //父菜单项
    Value string //值
}

/*
* 创建菜单项
*/
func CreateMenuItem()(*FCMenuItem){
    menuItem := new(FCMenuItem)
    menuItem.IsNotEmpty = true
    return menuItem
}

func (c *FCMenu)GetComboBox()(*FCView){
    length := len(c.ComboBox)
    if length > 0{
        return c.ComboBox[0]
    }else{
        noneComboBox := new(FCView)
        noneComboBox.IsNotEmpty = false
        return noneComboBox
    }
}

func (c *FCMenu)SetComboBox(cb *FCView){
    var pList []*FCView
    c.ComboBox = pList
    c.ComboBox = append(c.ComboBox, cb)
}

func (c *FCMenuItem)GetDropDownMenu()(*FCView){
    length := len(c.DropDownMenu)
    if length > 0{
        return c.DropDownMenu[0]
    }else{
        noneMenu := new(FCView)
        noneMenu.IsNotEmpty = false
        return noneMenu
    }
}

func (c *FCMenuItem)SetDropDownMenu(m *FCView){
    var pList []*FCView
    c.DropDownMenu = pList
    c.DropDownMenu = append(c.DropDownMenu, m)
}

func (c *FCMenuItem)GetParentMenu()(*FCView){
    length := len(c.ParentMenu)
    if length > 0{
        return c.ParentMenu[0]
    }else{
        noneMenu := new(FCView)
        noneMenu.IsNotEmpty = false
        return noneMenu
    }
}

func (c *FCMenuItem)SetParentMenu(m *FCView){
    var pList []*FCView
    c.ParentMenu = pList
    c.ParentMenu = append(c.ParentMenu, m)
}

func (c *FCMenuItem)GetParentItem()(*FCView){
    length := len(c.ParentItem)
    if length > 0{
        return c.ParentItem[0]
    }else{
        noneItem := new(FCView)
        noneItem.IsNotEmpty = false
        return noneItem
    }
}

func (c *FCMenuItem)SetParentItem(m *FCView){
    var pList []*FCView
    c.ParentItem = pList
    c.ParentItem = append(c.ParentItem, m)
}

/*
* 下拉列表
*/
type FCComboBox struct{
    DropDownMenu []*FCView //下拉菜单
    IsNotEmpty bool
    SelectedIndex int
}

/*
* 创建下拉列表
*/
func CreateComboBox()(*FCComboBox){
    comboBox := new(FCComboBox)
    comboBox.IsNotEmpty = true
    comboBox.SelectedIndex = -1
    return comboBox
}

func (c *FCComboBox)GetDropDownMenu()(*FCView){
    length := len(c.DropDownMenu)
    if length > 0{
        return c.DropDownMenu[0]
    }else{
        noneMenu := new(FCView)
        noneMenu.IsNotEmpty = false
        return noneMenu
    }
}

func (c *FCComboBox)SetDropDownMenu(m *FCView){
    var pList []*FCView
    c.DropDownMenu = pList
    c.DropDownMenu = append(c.DropDownMenu, m)
}

/*
* 多页夹的页
*/
type FCTabPage struct{
    HeaderButton []*FCView //页头的按钮
    IsNotEmpty bool
}

/*
* 创建多页夹的页
*/
func CreateTabPage()(*FCTabPage){
    tabPage := new(FCTabPage)
    tabPage.IsNotEmpty = true
    return tabPage
}

func (c *FCTabPage)GetHeaderButton()(*FCView){
    length := len(c.HeaderButton)
    if length > 0{
        return c.HeaderButton[0]
    }else{
        noneView := new(FCView)
        noneView.IsNotEmpty = false
        return noneView
    }
}

func (c *FCTabPage)SetHeaderButton(view *FCView){
    var pList []*FCView
    c.HeaderButton = pList
    c.HeaderButton = append(c.HeaderButton, view)
}

/*
* 多页夹
*/
type FCTabView struct{
    AnimationSpeed int //动画速度
    IsNotEmpty bool
    Layout string //布局方式
    TabPages []*FCView //页夹集合
    UnderLineColor string //下划线的颜色
    UnderLineSize float64 //下划线的宽度
    UnderPoint FCPoint //下划点
    UseAnimation bool //是否使用动画
}

/*
* 创建多页夹的页
*/
func CreateTabView()(*FCTabView){
    tabView := new(FCTabView)
    tabView.IsNotEmpty = true
    tabView.Layout = "top" 
    tabView.UnderLineColor = "none" 
    tabView.AnimationSpeed = 20 
    return tabView
}

/*
* 复选按钮
*/
type FCCheckBox struct{
    ButtonSize FCSize //按钮的大小
    Checked bool //是否选中
    IsNotEmpty bool
}

/*
* 创建复选按钮
*/
func CreateCheckBox()(*FCCheckBox){
    checkBox := new(FCCheckBox)
    checkBox.IsNotEmpty = true
    checkBox.ButtonSize = CreateSize(16, 16)
    return checkBox
}

/*
* 单选按钮
*/
type FCRadioButton struct{
    ButtonSize FCSize //按钮的大小
    Checked bool //是否选中
    GroupName string //组别
    IsNotEmpty bool
}

/*
* 创建单选按钮
*/
func CreateRadioButton()(*FCRadioButton){
    radioButton := new(FCRadioButton)
    radioButton.IsNotEmpty = true
    radioButton.ButtonSize = CreateSize(16, 16)
    return radioButton
}

/*
* 横竖布局
*/
type FCLayoutDiv struct{
    AutoWrap bool //是否自动换行
    IsNotEmpty bool
    LayoutStyle string //分割方式
}

/*
* 创建横竖布局
*/
func CreateLayoutDiv()(*FCLayoutDiv){
    layout := new(FCLayoutDiv)
    layout.IsNotEmpty = true
    layout.LayoutStyle = "lefttoright" 
    return layout
}

/*
* 分割布局
*/
type FCSplitLayoutDiv struct{
    FirstView []*FCView //第一个视图
    IsNotEmpty bool
    LayoutStyle string //布局方式
    OldSize FCSize //上次的尺寸
    SplitMode string //分割模式 percentsize百分比或absolutesize绝对值
    SplitPercent float64 //分割百分比
    SecondView []*FCView //第二个视图
    Splitter []*FCView //分割线
}

/*
* 创建分割布局
*/
func CreateSplitLayoutDiv()(*FCSplitLayoutDiv){
    split := new(FCSplitLayoutDiv)
    split.IsNotEmpty = true
    split.SplitMode = "absolutesize"
    split.SplitPercent = -1 
    split.LayoutStyle = "lefttoright"
    return split
}

func (c *FCSplitLayoutDiv)GetFirstView()(*FCView){
    length := len(c.FirstView)
    if length > 0{
        return c.FirstView[0]
    }else{
        noneView := new(FCView)
        noneView.IsNotEmpty = false
        return noneView
    }
}

func (c *FCSplitLayoutDiv)SetFirstView(view *FCView){
    var pList []*FCView
    c.FirstView = pList
    c.FirstView = append(c.FirstView, view)
}

func (c *FCSplitLayoutDiv)GetSecondView()(*FCView){
    length := len(c.SecondView)
    if length > 0{
        return c.SecondView[0]
    }else{
        noneView := new(FCView)
        noneView.IsNotEmpty = false
        return noneView
    }
}

func (c *FCSplitLayoutDiv)SetSecondView(view *FCView){
    var pList []*FCView
    c.SecondView = pList
    c.SecondView = append(c.SecondView, view)
}

func (c *FCSplitLayoutDiv)GetSplitter()(*FCView){
    length := len(c.Splitter)
    if length > 0{
        return c.Splitter[0]
    }else{
        noneView := new(FCView)
        noneView.IsNotEmpty = false
        return noneView
    }
}

func (c *FCSplitLayoutDiv)SetSplitter(view *FCView){
    var pList []*FCView
    c.Splitter = pList
    c.Splitter = append(c.Splitter, view)
}

/*
* 表格列
*/
type FCGridColumn struct {
    AllowSort bool //是否允许排序
    AllowResize bool //是否允许改变大小
    BackColor string //背景色
    BorderColor string //边线颜色
    Bounds FCRect //区域
    CellAlign string //left:居左 center:居中 right:居右
	ColName string //名称
    ColType string //类型 string:字符串 double:浮点型 int:整型 bool: 布尔型
    Font string //字体
    Frozen bool //是否冻结
    Index int //索引
    IsNotEmpty bool
    Sort string //排序模式
    Text string //文字
    TextColor string //文字颜色
    Visible bool //是否可见
    Width float64 //宽度
    WidthStr string //宽度字符串 
}

/*
* 初始化
*/
func CreateGridColumn()(*FCGridColumn){
    col := new(FCGridColumn)
    col.Width = 120
    col.Font = "Default,14" 
    col.BackColor = "rgb(200,200,200)" 
    col.BorderColor = "rgb(150,150,150)" 
    col.TextColor = "rgb(50,50,50)" 
    col.Sort = "none"
    col.Visible = true 
    col.Index = -1 
    col.CellAlign = "left"
    col.AllowSort = true
    col.IsNotEmpty = true
    return col
}

/*
* 表格单元格
*/
type FCGridCell struct {
    BackColor string //背景色
    BorderColor string //边线色
    ColSpan int //列距
    Column []*FCGridColumn //所在列
    Digit int //保留小数的位数
    Font string //字体
    IsNotEmpty bool
    Row []*FCGridRow //所在行
    RowSpan int //行距
    TextColor string //前景色
    Value string //值
    View []*FCView //所在行
}

/*
* 初始化
*/
func CreateGridCell()(*FCGridCell){
    cell := new(FCGridCell)
    cell.BackColor = "rgb(255,255,255)"
    cell.BorderColor = "rgb(150,150,150)" 
    cell.TextColor = "rgb(0,0,0)" 
    cell.Font = "Default,14" 
    cell.ColSpan = 1
    cell.RowSpan = 1 
    cell.IsNotEmpty = true
    cell.Digit = -1
    return cell
}

func (c *FCGridCell)GetColumn()(*FCGridColumn){
    length := len(c.Column)
    if length > 0{
        return c.Column[0]
    }else{
        noneColumn := new(FCGridColumn)
        noneColumn.IsNotEmpty = false
        return noneColumn
    }
}

func (c *FCGridCell)SetColumn(col *FCGridColumn){
    var pList []*FCGridColumn
    c.Column = pList
    c.Column = append(c.Column, col)
}

func (c *FCGridCell)GetRow()(*FCGridRow){
    length := len(c.Row)
    if length > 0{
        return c.Row[0]
    }else{
        noneRow := new(FCGridRow)
        noneRow.IsNotEmpty = false
        return noneRow
    }
}

func (c *FCGridCell)SetRow(r *FCGridRow){
    var pList []*FCGridRow
    c.Row = pList
    c.Row = append(c.Row, r)
}

func (c *FCGridCell)GetView()(*FCView){
    length := len(c.View)
    if length > 0{
        return c.View[0]
    }else{
        noneView := new(FCView)
        noneView.IsNotEmpty = false
        return noneView
    }
}

func (c *FCGridCell)SetView(v *FCView){
    var pList []*FCView
    c.View = pList
    c.View = append(c.View, v)
}

/*
* 表格行
*/
type FCGridRow struct {
    Cells []*FCGridCell //单元格
    IsNotEmpty bool
    Index int //索引
	Selected bool //是否选中
    SortColIndex int //排序的列
    Visible bool //是否可见
}

/*
* 初始化
*/
func CreateGridRow()(*FCGridRow){
    row := new(FCGridRow)
    row.Visible = true 
    row.Index = -1
    row.IsNotEmpty = true
    return row
}

/*
* 表格
*/
type FCGrid struct{
    Columns []*FCGridColumn //所有的列
    HeaderHeight float64 //头部高度
    IsNotEmpty bool
    RowHeight float64 //行高
    Rows []*FCGridRow //包含的所有行
    SelectedRowColor string //选中行的颜色
    OnClickGridCell ClickGridCellEventCallBack //点击单元格的回调
    OnClickGridColumn ClickGridColumnEventCallBack //点击列的回调
    OnPaintGridCell PaintGridCellEventCallBack //绘制单元格的回调
    OnPaintGridColumn PaintGridColumnEventCallBack //绘制表格列的回调
}

/*
* 初始化表格
*/
func CreateGrid()(*FCGrid){
    grid := new(FCGrid)
    grid.IsNotEmpty = true
    grid.RowHeight = 30
    grid.HeaderHeight = 30
    grid.SelectedRowColor = "rgb(125,125,125)" 
    return grid
}

/*
* 树
*/
type FCTree struct{
    CheckBoxWidth float64 //复选框占用的宽度
    ChildNodes []*FCTreeNode //子节点
    CollapsedWidth float64 //折叠按钮占用的宽度
    HeaderHeight float64 //头部高度
    Indent float64 //缩进
    IsNotEmpty bool
    RowHeight float64 //行高
    ShowCheckBox bool //是否显示复选框
    Rows []*FCTreeRow //包含的所有行
    Columns []*FCTreeColumn //所有的列
    OnClickTreeNode ClickTreeNodeEventCallBack //点击树节点的回调
    OnPaintTreeNode PaintTreeNodeEventCallBack //绘制树节点的回调
}

/*
* 初始化树
*/
func CreateTree()(*FCTree){
    tree := new(FCTree)
    tree.IsNotEmpty = true
    tree.RowHeight = 30 
    tree.HeaderHeight = 30 
    tree.Indent = 20 
    tree.CheckBoxWidth = 25
    tree.CollapsedWidth = 25
    return tree
}

/*
* 树的列
*/
type FCTreeColumn struct {
    Bounds FCRect //区域
    Index int //索引
    IsNotEmpty bool
    Visible bool //是否可见
	Width float64 //宽度 
    WidthStr string //宽度字符串
}

/*
* 初始化
*/
func CreateTreeColumn()(*FCTreeColumn){
    col := new(FCTreeColumn)
    col.Width = 120 
    col.Visible = true 
    col.Index = -1 
    col.IsNotEmpty = true
    return col
}

/*
* 树的列
*/
type FCTreeRow struct {
    Cells []*FCTreeNode //单元格
    Index int //索引
    IsNotEmpty bool
	Selected bool //是否选中
    Visible bool //是否可见
}

/*
* 初始化
*/
func CreateTreeRow()(*FCTreeRow){
    row := new(FCTreeRow)
    row.Visible = true 
    row.Index = -1 
    row.IsNotEmpty = true
    return row
}

/*
* 树节点
*/
type FCTreeNode struct {
    AllowCollapsed bool //是否允许折叠
    BackColor string //背景色
    Checked bool //是否选中
    ChildNodes []*FCTreeNode //子节点
    Collapsed bool //是否折叠
    Column []*FCTreeColumn //所有的列
    Font string //字体
    Indent float64 //缩进
    IsNotEmpty bool
    ParentNode []*FCTreeNode
    Row []*FCTreeRow //包含的所有行
    TextColor string //前景色
	Value string //值 
}

/*
* 初始化
*/
func CreateTreeNode()(*FCTreeNode){
    node := new(FCTreeNode)
    node.BackColor = "rgb(255,255,255)" 
    node.TextColor = "rgb(0,0,0)" 
    node.Font = "Default,14" 
    node.AllowCollapsed = true 
    node.IsNotEmpty = true
    return node
}

func (c *FCTreeNode)GetColumn()(*FCTreeColumn){
    length := len(c.Column)
    if length > 0{
        return c.Column[0]
    }else{
        noneColumn := new(FCTreeColumn)
        noneColumn.IsNotEmpty = false
        return noneColumn
    }
}

func (c *FCTreeNode)SetColumn(col *FCTreeColumn){
    var pList []*FCTreeColumn
    c.Column = pList
    c.Column = append(c.Column, col)
}

func (c *FCTreeNode)GetRow()(*FCTreeRow){
    length := len(c.Row)
    if length > 0{
        return c.Row[0]
    }else{
        noneColumn := new(FCTreeRow)
        noneColumn.IsNotEmpty = false
        return noneColumn
    }
}

func (c *FCTreeNode)SetRow(r *FCTreeRow){
    var pList []*FCTreeRow
    c.Row = pList
    c.Row = append(c.Row, r)
}

func (c *FCTreeNode)GetParentNode()(*FCTreeNode){
    length := len(c.ParentNode)
    if length > 0{
        return c.ParentNode[0]
    }else{
        noneColumn := new(FCTreeNode)
        noneColumn.IsNotEmpty = false
        return noneColumn
    }
}

func (c *FCTreeNode)SetParentNode(node *FCTreeNode){
    var pList []*FCTreeNode
    c.ParentNode = pList
    c.ParentNode = append(c.ParentNode, node)
}

/*
* 证券数据结构
*/
type SecurityData struct {
	Amount float64 //成交额
    Close float64 //收盘价
    Date float64 //日期，为1970年到现在的秒
    High float64 //最高价
    Low float64 //最低价
    Open float64 //开盘价
    Volume float64 //成交额
}

/*
* 基础图形
*/
type BaseShape struct {
    Color string //颜色
    Color2 string //颜色2
    Datas []float64 //第一组数据
    Datas2 []float64 //第二组数据
	DivIndex int //所在层
    IsNotEmpty bool
    LeftOrRight bool //依附于左轴或右轴
    LineWidth float64 //线的宽度
    ShapeName string //名称
    ShapeType string //类型
    ShowHideDatas []float64 //控制显示隐藏的数据
    Style string //样式
    Text string //显示的文字
    Title string //第一个标题
    Title2 string //第二个标题
    Value float64 //显示文字的值
}

/*
* 初始化
*/
func CreateBaseShape()(*BaseShape){
    shape := new(BaseShape)
    shape.ShapeType = "line"
    shape.LineWidth = 1 
    shape.Color = "none" 
    shape.Color2 = "none" 
    shape.LeftOrRight = true 
    shape.IsNotEmpty = true
    return shape
}

/*
* 画线工具结构
*/
type FCPlot struct {
    Key1 float64 //第一个键
    Key2 float64 //第二个键
    Key3 float64 //第三个键
    IsNotEmpty bool
    LineColor string //线的颜色
    LineWidth float64 //线的宽度
    PointColor string //线的颜色
    PlotType string //线的类型
    StartKey1 float64 //移动前第一个键
    StartValue1 float64 //移动前第一个值
    StartKey2 float64 //移动前第二个键
    StartValue2 float64 //移动前第二个值
    StartKey3 float64 //移动前第三个键
    StartValue3 float64 //移动前第三个值
    Value1 float64 //第一个值
    Value2 float64 //第二个值
    Value3 float64 //第三个值
}

/*
* 初始化
*/
func CreatePlot()(*FCPlot){
    plot := new(FCPlot)
    plot.PlotType = "Line" 
    plot.LineColor = "rgb(0,0,0)"
    plot.PointColor = "rgba(0,0,0,120)" 
    plot.LineWidth = 1 
    plot.IsNotEmpty = true
    return plot
}

/*
* 图表
*/
type FCChart struct{
    AutoFillHScale bool //是否填充满X轴
    AllowDragChartDiv bool //是否允许拖拽图层
    CandleDistance float64 //蜡烛线的距离
    CandleMax float64 //蜡烛线的最大值
    CandleMin float64 //蜡烛线的最小值
    CandleMaxRight float64 //蜡烛线的右轴最大值
    CandleMinRight float64 //蜡烛线的右轴最小值
    CrossTipColor string //十字线标识的颜色
    CrossLineColor string //十字线的颜色
    CandleDigit int //图表层保留小数的位数
    CandleDivPercent float64 //图表层的占比
    CandlePaddingTop float64 //图表层的上边距
    CandlePaddingBottom float64 //图表层的下边距
    CrossStopIndex int //鼠标停留位置
    Cycle string //周期
    Data []*SecurityData //子节点
    DownColor string //下跌颜色
    FirstVisibleIndex int //起始可见的索引
    GridColor string //网格颜色
    HScalePixel float64 //蜡烛线的宽度
    HScaleHeight float64 //X轴的高度
    HScaleFormat string //X轴的格式化字符，例如YYYY-mm-dd HH:MM:SS
    HScaleTextDistance float64 //X轴的文字间隔
    IndMax float64 //指标层的最大值
    IndMin float64 //指标的最小值
    IndMax2 float64 //指标层2的最大值
    IndMin2 float64 //指标层2的最小值
    IndMaxRight float64 //指标层的右轴最大值
    IndMinRight float64 //指标层的右轴最小值
    IndMax2Right float64 //指标层2的右轴最大值
    IndMin2Right float64 //指标层2的右轴最小值
    IndDigit int //指标层保留小数的位数
    IndDigit2 int //指标层2保留小数的位数
    IndDivPercent float64 //指标层的占比
    IndDivPercent2 float64 //指标层2的占比
    IndPaddingTop float64 //指标层的上边距
    IndPaddingBottom float64 //指标层的下边距
    IndPaddingTop2 float64 //指标层2的上边距
    IndPaddingBottom2 float64 //指标层2的下边距
    IndicatorColors []string
    IsNotEmpty bool //是否不为空
    LeftVScaleWidth float64 //左轴宽度
    LastVisibleIndex int //结束可见的索引
    LastRecordIsVisible bool //最后记录是否可见
    LastVisibleKey float64 //最后可见的主键
    LastValidIndex int //最后有效数据索引
    LineWidthChart float64
    MainIndicator string //主图指标
    Magnitude int //成交量的比例
    MidColor string  //中间色
    OffsetX float64 //横向绘图偏移
    PlotPointSizeChart float64 //画线的选中点大小
    Plots []*FCPlot //画线
    RightVScaleWidth float64 //右轴宽度
    RightSpace float64 //右侧空间
    ScaleColor string //刻度的颜色
    ShowIndicator string //显示指标
    ShowCrossLine bool //是否显示十字线
    SelectPlotPoint int //选中画线的点
    StartMovePlot bool //选中画线
    SelectShape string //选中的图形
    SelectShapeEx string //选中的图形信息
    Shapes []*BaseShape //扩展图形
    SPlot []*FCPlot //选中的线条
    TargetOldX float64 //缩小时旧的位置1
	TargetOldX2 float64 //放大时旧的位置2
    TouchPosition FCPoint //鼠标坐标
    VolMax float64 //成交量层的最大值
    VolMin float64 //成交量层的最小值
    VolMaxRight float64 //成交量层的右轴最大值
    VolMinRight float64 //成交量层的右轴最小值
    VolDigit int //成交量层保留小数的位数
    VolDivPercent float64 //成交量层的占比
    VolPaddingTop float64 //成交量层的上边距
    VolPaddingBottom float64 //成交量层的下边距
    VScaleDistance float64 //纵轴的间隔
    VScaleType string //纵轴的类型 log10代表指数坐标
    UpColor string //上涨颜色
    KChart float64
    BChart float64
    OXChart float64
    OYChart float64
    RChart float64
    GridStepChart float64 //网格计算临时变量
    GridDigitChart int //网格计算临时变量
    CandleStyle string
    BarStyle string
    FirstOpen float64
    //拖动滚动的缓存
    FirstIndexCacheChart int
    FirstTouchIndexCacheChart int
    FirstTouchPointCacheChart FCPoint
    LastIndexCacheChart int
    SecondTouchIndexCacheChart int
    SecondTouchPointCacheChart FCPoint
    FirstPaddingTop float64
    FirtstPaddingBottom float64
    TouchDownPointChart FCPoint
    AddingPlotChart string
    X4Chart float64
    Y4Chart float64
    NHighChart float64
    NLowChart float64
    XChart float64
    YChart float64
    WChart float64
    HChart float64
    UpSubValue float64
    DownSubValue float64
    Allema12 []float64
    Allema26 []float64
    Alldifarr []float64
    Alldeaarr []float64
    Allmacdarr []float64
    BollUp []float64
    BollDown []float64
    BollMid []float64
    Bias1 []float64
    Bias2 []float64
    Bias3 []float64
    KdjK []float64
    KdjD []float64
    KdjJ []float64
    Rsi1 []float64
    Rsi2 []float64
    Rsi3 []float64
    Roc []float64
    RocMa []float64
    Wr1 []float64
    Wr2 []float64
    Cci []float64
    Bbi []float64
    Trix []float64
    TrixMa []float64
    Dma1 []float64
    Dma2 []float64
    Ma5 []float64
    Ma10 []float64
    Ma20 []float64
    Ma30 []float64
    Ma120 []float64
    Ma250 []float64
    CloseArr []float64
    OnCalculateChartMaxMin CalculateChartMaxMinEventCallBack //计算最大最小值的回调
    OnPaintChartScale PaintEventCallBack //绘制坐标轴回调
    OnPaintChartHScale PaintEventCallBack //绘制坐标轴回调
    OnPaintChartStock PaintEventCallBack //绘制图表回调
    OnPaintChartPlot PaintEventCallBack //绘制画线回调
    OnPaintChartCrossLine PaintEventCallBack //绘制十字线回调
}

/*
* 创建图表
*/
func CreateChart()(*FCChart){
    chart := new(FCChart)
    chart.IsNotEmpty = true
    chart.HScalePixel = 11
    chart.DownColor = "rgb(15,193,118)" 
    chart.LeftVScaleWidth = 80
    chart.MidColor = "none"
    chart.UpColor = "rgb(219,68,83)" 
    chart.FirstVisibleIndex = -1 
    chart.LastVisibleIndex = -1
    chart.HScaleHeight = 30
    chart.ScaleColor = "rgb(255,0,0)"
    chart.CrossTipColor = "rgb(50,50,50)" 
    chart.CrossLineColor = "rgb(100,100,100)"
    chart.CandleDigit = 2 
    chart.IndDigit = 2 
    chart.IndDigit2 = 2 
    chart.LastRecordIsVisible = true
    chart.CandleDivPercent = 0.5 
    chart.VolDivPercent = 0.2 
    chart.IndDivPercent = 0.3 
    chart.GridColor = "rgba(255,0,0,120)" 
    chart.Magnitude = 1 
    chart.ShowCrossLine = false
    chart.CandlePaddingTop = 30
    chart.CandlePaddingBottom = 30 
    chart.VolPaddingTop = 20 
    chart.VolPaddingBottom = 0 
    chart.IndPaddingTop = 20
    chart.IndPaddingBottom = 20 
    chart.IndPaddingTop2 = 20 
    chart.IndPaddingBottom2 = 20
    chart.VScaleDistance = 35
    chart.VScaleType = "standard" 
    chart.SelectPlotPoint =-1 
    chart.CrossStopIndex =-1 
    chart.Cycle = "second" 
    chart.LastValidIndex =-1 
    chart.HScaleTextDistance = 10 
    chart.LineWidthChart = 1
    chart.PlotPointSizeChart = 20 
    chart.FirstIndexCacheChart =-1
    chart.FirstTouchIndexCacheChart =-1
    chart.LastIndexCacheChart =-1
    chart.SecondTouchIndexCacheChart =-1
    var indicatorColors[]string
	indicatorColors = append(indicatorColors, "rgb(100,100,100)")
	indicatorColors = append(indicatorColors, "rgb(206,147,27)")
	indicatorColors = append(indicatorColors, "rgb(150,0,150)")
	indicatorColors = append(indicatorColors, "rgb(255,0,0)")
	indicatorColors = append(indicatorColors, "rgb(0,150,150)")
	indicatorColors = append(indicatorColors, "rgb(0,150,0)")
	indicatorColors = append(indicatorColors, "rgb(59,174,218)")
	indicatorColors = append(indicatorColors, "rgb(50,50,50)")
    chart.IndicatorColors = indicatorColors
    chart.CandleStyle = "rect"
    chart.BarStyle = "rect"
    return chart
}

func (c *FCChart)GetSelectedPlot()(*FCPlot){
    length := len(c.SPlot)
    if length > 0{
        return c.SPlot[0]
    }else{
        nonePlot := new(FCPlot)
        nonePlot.IsNotEmpty = false
        return nonePlot
    }
}

func (c *FCChart)SetSelectedPlot(plot *FCPlot){
    var pList []*FCPlot
    c.SPlot = pList
    c.SPlot = append(c.SPlot, plot)
}

/*
* 日历
*/
type FCCalendar struct{
    DayDiv []*DayDiv //日层
    HeadDiv []*HeadDiv //头部层
    IsNotEmpty bool //是否不为空
    Mode string //模式
    MonthDiv []*MonthDiv //月层
    SelectedDay []*CDay //选中日
    TimeDiv []*TimeDiv //时间层
    UseAnimation bool //是否使用动画
    YearDiv []*YearDiv //年层
    Years map[int]*CYear //日历
    OnPaintCalendarDayButton PaintCalendarDayButtonEventCallBack  //绘制日历的日按钮回调
    OnPaintCalendarMonthButton PaintCalendarMonthButtonEventCallBack //绘制日历的月按钮回调
    OnPaintCalendarYearButton PaintCalendarYearButtonEventCallBack //绘制日历的年按钮回调
    OnPaintCalendarHeadDiv PaintCalendarHeadDivEventCallBack //绘制日历头部回调
}

/*
* 创建日历
*/
func CreateCalendar()(*FCCalendar){
    calendar := new(FCCalendar)
    calendar.IsNotEmpty = true
    calendar.Mode = "day"
    calendar.Years = make(map[int]*CYear)
    calendar.IsNotEmpty = true
    return calendar
}

/*
* 月层
*/
type MonthDiv struct {
    ADirection int //动画的方向
    ATick int //动画当前帧数
    ATotalTick int //动画总帧数
    IsNotEmpty bool
    Month int //月份
    MonthButtons []*MonthButton //月的按钮
    MonthButtonsAm []*MonthButton //动画日期的集合
    Year int //年份  
}

/*
* 初始化
*/
func CreateMonthDiv()(*MonthDiv){
    monthDiv := new(MonthDiv)
    monthDiv.IsNotEmpty = true
    monthDiv.ATotalTick = 40
    return monthDiv
}

/*
* 年层
*/
type YearDiv struct {
    ADirection int //动画的方向
    ATick int //动画当前帧数
    ATotalTick int //动画总帧数
    IsNotEmpty bool
    StartYear int //开始年份
    YearButtons []*YearButton //年的按钮
    YearButtonsAm []*YearButton //动画日期的集合
}

/*
* 初始化
*/
func CreateYearDiv()(*YearDiv){
    yearDiv := new(YearDiv)
    yearDiv.IsNotEmpty = true
    yearDiv.ATotalTick = 40
    return yearDiv
}

/*
* 头部层
*/
type HeadDiv struct {
    ArrowColor string //箭头颜色
    BackColor string //箭头颜色
    Bounds FCRect //显示区域
    IsNotEmpty bool
    TextColor string //文字颜色
    TitleFont string //标题字体
    WeekFont string //星期字体
}

/*
* 初始化
*/
func CreateHeadDiv()(*HeadDiv){
    headDiv := new(HeadDiv)
    headDiv.IsNotEmpty = true
    headDiv.TitleFont = "Default,20" 
    headDiv.WeekFont = "Default,14" 
    headDiv.ArrowColor = "rgb(150,150,150)"
    headDiv.BackColor = "rgb(255,255,255)"
    headDiv.TextColor = "rgb(0,0,0)" 
    return headDiv
}

/*
* 时间层
*/
type TimeDiv struct {
    Bounds FCRect //显示区域
    IsNotEmpty bool
}

/*
* 初始化
*/
func CreateTimeDiv()(*TimeDiv){
    timeDiv := new(TimeDiv)
    timeDiv.IsNotEmpty = true
    return timeDiv
}

/*
* 头部层
*/
type CYear struct {
    IsNotEmpty bool
    Months map[int]*CMonth
    Year int //年
}

/*
* 初始化
*/
func CreateCYear()(*CYear){
    cYear := new(CYear)
    cYear.IsNotEmpty = true
    cYear.Months = make(map[int]*CMonth)
    return cYear
}

/*
* 月的结构
*/
type CMonth struct {
    Days map[int]*CDay
    IsNotEmpty bool
    Month int //月
    Year int //年
}

/*
* 初始化
*/
func CreateCMonth()(*CMonth){
    cMonth := new(CMonth)
    cMonth.IsNotEmpty = true
    cMonth.Days = make(map[int]*CDay)
    return cMonth
}

/*
* 日的结构
*/
type CDay struct {
    Day int //日
    IsNotEmpty bool
    Month int //月
    Year int //年
}

/*
* 初始化
*/
func CreateCDay()(*CDay){
    cDay := new(CDay)
    cDay.IsNotEmpty = true
    return cDay
}

func (c *FCCalendar)GetDayDiv()(*DayDiv){
    length := len(c.DayDiv)
    if length > 0{
        return c.DayDiv[0]
    }else{
        noneDayDiv := new(DayDiv)
        noneDayDiv.IsNotEmpty = false
        return noneDayDiv
    }
}

func (c *FCCalendar)SetDayDiv(d *DayDiv){
    var pList []*DayDiv
    c.DayDiv = pList
    c.DayDiv = append(c.DayDiv, d)
}

func (c *FCCalendar)GetHeadDiv()(*HeadDiv){
    length := len(c.HeadDiv)
    if length > 0{
        return c.HeadDiv[0]
    }else{
        noneHeadDiv := new(HeadDiv)
        noneHeadDiv.IsNotEmpty = false
        return noneHeadDiv
    }
}

func (c *FCCalendar)SetHeadDiv(h *HeadDiv){
    var pList []*HeadDiv
    c.HeadDiv = pList
    c.HeadDiv = append(c.HeadDiv, h)
}

func (c *FCCalendar)GetMonthDiv()(*MonthDiv){
    length := len(c.MonthDiv)
    if length > 0{
        return c.MonthDiv[0]
    }else{
        noneMonthDiv := new(MonthDiv)
        noneMonthDiv.IsNotEmpty = false
        return noneMonthDiv
    }
}

func (c *FCCalendar)SetMonthDiv(m *MonthDiv){
    var pList []*MonthDiv
    c.MonthDiv = pList
    c.MonthDiv = append(c.MonthDiv, m)
}

func (c *FCCalendar)GetYearDiv()(*YearDiv){
    length := len(c.YearDiv)
    if length > 0{
        return c.YearDiv[0]
    }else{
        noneYearDiv := new(YearDiv)
        noneYearDiv.IsNotEmpty = false
        return noneYearDiv
    }
}

func (c *FCCalendar)SetYearDiv(y *YearDiv){
    var pList []*YearDiv
    c.YearDiv = pList
    c.YearDiv = append(c.YearDiv, y)
}

func (c *FCCalendar)GetTimeDiv()(*TimeDiv){
    length := len(c.TimeDiv)
    if length > 0{
        return c.TimeDiv[0]
    }else{
        noneTimeDiv := new(TimeDiv)
        noneTimeDiv.IsNotEmpty = false
        return noneTimeDiv
    }
}

func (c *FCCalendar)SetTimeDiv(t *TimeDiv){
    var pList []*TimeDiv
    c.TimeDiv = pList
    c.TimeDiv = append(c.TimeDiv, t)
}

func (c *FCCalendar)GetSelectedDay()(*CDay){
    length := len(c.SelectedDay)
    if length > 0{
        return c.SelectedDay[0]
    }else{
        noneDay := new(CDay)
        noneDay.IsNotEmpty = false
        return noneDay
    }
}

func (c *FCCalendar)SetSelectedDay(d *CDay){
    var pList []*CDay
    c.SelectedDay = pList
    c.SelectedDay = append(c.SelectedDay, d)
}

/*
* 日的按钮
*/
type DayButton struct {
    BackColor string //背景颜色
    BorderColor string //文字颜色
    Bounds FCRect //显示区域
    CDay []*CDay
    Font string //字体
    InThisMonth bool //是否在本月
    IsNotEmpty bool
    Selected bool //是否被选中
    TextColor string //文字颜色
    TextColor2 string //第二个文字颜色
    Visible bool //是否可见
}

/*
* 初始化
*/
func CreateDayButton()(*DayButton){
    dayButton := new(DayButton)
    dayButton.IsNotEmpty = true
    dayButton.Visible = true 
    dayButton.Font = "Default,16" 
    dayButton.TextColor = "rgb(0,0,0)" 
    dayButton.BackColor = "none" 
    dayButton.TextColor2 = "rgb(50,50,50)" 
    dayButton.BorderColor = "rgb(150,150,150)" 
    return dayButton
}

func (c *DayButton)GetDay()(*CDay){
    length := len(c.CDay)
    if length > 0{
        return c.CDay[0]
    }else{
        noneDay := new(CDay)
        noneDay.IsNotEmpty = false
        return noneDay
    }
}

func (c *DayButton)SetDay(d *CDay){
    var pList []*CDay
    c.CDay = pList
    c.CDay = append(c.CDay, d)
}

/*
* 月的按钮
*/
type MonthButton struct {
    BackColor string //背景颜色
    BorderColor string //文字颜色
    Bounds FCRect //显示区域
    Font string //字体
    IsNotEmpty bool
    Month int //月
    Selected bool //是否被选中
    TextColor string //文字颜色
    Visible bool //是否可见
    Year int //年 
}

/*
* 初始化
*/
func CreateMonthButton()(*MonthButton){
    monthButton := new(MonthButton)
    monthButton.IsNotEmpty = true
    monthButton.Visible = true 
    monthButton.Font = "Default,16" 
    monthButton.TextColor = "rgb(0,0,0)" 
    monthButton.BackColor = "none" 
    monthButton.BorderColor = "rgb(150,150,150)" 
    return monthButton
}

/*
* 年的按钮
*/
type YearButton struct {
    BackColor string //背景颜色
    BorderColor string //文字颜色
    Bounds FCRect //显示区域
    Font string //字体
    IsNotEmpty bool
    Selected bool //是否被选中
    TextColor string //文字颜色
    Visible bool //是否可见
    Year int //年
}

/*
* 初始化
*/
func CreateYearButton()(*YearButton){
    yearButton := new(YearButton)
    yearButton.IsNotEmpty = true
    yearButton.Visible = true 
    yearButton.Font = "Default,16" 
    yearButton.TextColor = "rgb(0,0,0)" 
    yearButton.BackColor = "none" 
    yearButton.BorderColor = "rgb(150,150,150)"
    return yearButton
}

/*
* 日期层
*/
type DayDiv struct {
     AClickRowFrom int //点击时的上月的行
     AClickRowTo int //点击时的当月的行
     ADirection int //动画的方向
     ATick int //动画当前帧数
     ATotalTick int //动画总帧数
     DayButtons []*DayButton //日期的集合
     DayButtonsAm []*DayButton //动画日期的集合
     IsNotEmpty bool
}

/*
* 初始化
*/
func CreateDayDiv()(*DayDiv){
    dayDiv := new(DayDiv)
    dayDiv.IsNotEmpty = true
    dayDiv.ATotalTick = 40 
    return dayDiv
}

/*
* 数字转换成字符串，指定保留位数
*/
func ToFixed(value float64, digit int)(string){
    return strconv.FormatFloat(value, 'f', digit, 64)
}

/*
* 添加顶层视图
* view 视图
* paint 绘图对象
*/
func AddView(view *FCView, paint *FCPaint) {
    view.SetPaint(paint)
    paint.Views = append(paint.Views, view)
}

/*
* 添加到父视图
* view 视图
* parent 父视图
*/
func AddViewToParent(view *FCView, parent *FCView) {
    view.SetPaint(parent.GetPaint())
    parent.Views = append(parent.Views, view)
    view.SetParent(parent)
}

/*
* 插入到顶层视图
* view 视图
* paint 绘图对象
* index 索引
*/
func InsertView(view *FCView, paint *FCPaint, index int) {
    view.SetPaint(paint)
    newViews := paint.Views[:index]
    newViews = append(newViews, view)
    newViews = append(newViews, paint.Views[index:]...)
    paint.Views = newViews
}

/*
* 插入到到父视图
* view 视图
* parent 父视图
* index 索引
*/
func InsertViewToParent(view *FCView, parent *FCView, index int) {
    view.SetPaint(parent.GetPaint())
    newViews := parent.Views[:index]
    newViews = append(newViews, view)
    newViews = append(newViews, parent.Views[index:]...)
    parent.Views = newViews
    view.SetParent(parent)
}

/*
* 清除视图
*paint 绘图对象
*/
func ClearViews(paint *FCPaint){
    var views []*FCView
    paint.Views = views
}

/*
* 移除顶层视图
* view 视图
* paint 绘图对象
*/
func RemoveView(view *FCView, paint *FCPaint) {
    if len(paint.Views) > 0 {
        for i := 0; i < len(paint.Views); i++ {
            if paint.Views[i] == view {
                paint.Views = append(paint.Views[:i], paint.Views[i + 1:]...)
                break
            }
        }
    }
}

/*
* 从父视图中移除
* view 视图
* parent 父视图
*/
func RemoveViewFromParent(view *FCView, parent *FCView) {
    if len(parent.Views) > 0 {
        for i := 0; i < len(parent.Views); i++ {
            if parent.Views[i] == view {
                parent.Views = append(parent.Views[:i], parent.Views[i + 1:]...)
                break
            }
        }
    }
}

/*
* 获取绝对位置X
* view:视图
*/
func ClientX(view *FCView)(float64) {
    if view.IsNotEmpty {
        cLeft := view.Location.X
        pView := view.GetParent()
        if pView.IsNotEmpty {
            if pView.DisplayOffset && pView.ScrollH != 0 {
                return cLeft + ClientX(pView) - pView.ScrollH
            } else {
                return cLeft + ClientX(pView)
            }
        } else {
            return cLeft
        }
    } else {
        return 0
    }
}

/*
* 获取绝对位置Y
* view:视图
*/
func ClientY(view *FCView)(float64) {
    if view.IsNotEmpty {
      cTop := view.Location.Y
      pView := view.GetParent()
      if pView.IsNotEmpty {       
          if pView.DisplayOffset && pView.ScrollV != 0 {
            return cTop + ClientY(pView) - pView.ScrollV
          } else {
            return cTop + ClientY(pView)
          }
      } else {
          return cTop
      }
  } else {
      return 0
  }
}

/*
* 是否包含坐标
* view:视图
* mp:坐标
*/
func ContainsPoint(view *FCView, mp FCPoint)(bool){
    if IsViewEnabled(view){
        clx := ClientX(view)
        cly := ClientY(view)
        size := view.Size
        cp := CreatePoint(mp.X - clx, mp.Y - cly)
        if cp.X >= 0 && cp.X <= size.Cx &&
            cp.Y >= 0 && cp.Y <= size.Cy {
            return true
        } else {
            return false
        }
    }else{
        return false
    }
}

/*
* 根据名称查找视图
* name:名称
* views:视图集合
*/
func FindViewByName(name string, views []*FCView)(*FCView) {
    size := len(views)
    if(size > 0){
        for i := 0; i < size; i++ {
            view := views[i]
            if view.ViewName == name {
                return view
            } else {
                if len(view.Views) > 0 {
                    subView := FindViewByName(name, view.Views)
                    if subView.IsNotEmpty {
                        return subView
                    }
                }
            }
        }
    }
    noneView := new(FCView)
    noneView.IsNotEmpty = false
	return noneView
}

/*
* 根据坐标查找视图
* mp:坐标
* views:视图集合
*/
func FindView(mp FCPoint, views []*FCView)(*FCView) {
    size := len(views)
    if size > 0{
        for i := 0; i < size; i++ {
            view := views[size - i - 1]
            if view.Visible && view.TopMost {
                hasPoint := false
                paint := view.GetPaint()
                if(paint.OnContainsPoint != nil){
                    hasPoint = paint.OnContainsPoint(view, mp)
                }else{
                    hasPoint = ContainsPoint(view, mp)
                }
                if hasPoint {
                    if view.VScrollIsVisible {
                        clx := ClientX(view)
                        if mp.X >= clx + view.Size.Cx - view.ScrollSize {
                            return view
                        }
                    }
                    if view.HScrollIsVisible {
                        cly := ClientY(view)
                        if mp.Y >= cly + view.Size.Cy - view.ScrollSize {
                            return view
                        }
                    }
                    if len(view.Views) > 0 {
                        subView := FindView(mp, view.Views)
                        if subView.IsNotEmpty {
                            return subView
                        }
                    }
                    return view
                }
            }
        }
        for i := 0; i < size; i++ {
            view := views[size - i - 1]
            if view.Visible && !view.TopMost {
                hasPoint := false
                paint := view.GetPaint()
                if(paint.OnContainsPoint != nil){
                    hasPoint = paint.OnContainsPoint(view, mp)
                }else{
                    hasPoint = ContainsPoint(view, mp)
                }
                if hasPoint {
                    if view.VScrollIsVisible {
                        clx := ClientX(view)
                        if mp.X >= clx + view.Size.Cx - view.ScrollSize {
                            return view
                        }
                    }
                    if (view.HScrollIsVisible) {
                        cly := ClientY(view)
                        if mp.Y >= cly + view.Size.Cy - view.ScrollSize {
                            return view
                        }
                    }
                    if len(view.Views) > 0 {
                        subView := FindView(mp, view.Views)
                        if subView.IsNotEmpty {
                            return subView
                        }
                    }
                    return view
                }
            }
        }
    }
    noneView := new(FCView)
    noneView.IsNotEmpty = false
	return noneView
}

/*
* 是否重绘时可见
* view:视图
*/
func IsPaintVisible(view *FCView)(bool) {
    if view.Visible {
        pView := view.GetParent()
        if pView.IsNotEmpty {
            if pView.Visible {
                return IsPaintVisible(pView)
            } else {
                return false
            }
        } else {
            return true
        }
    } else {
        return false
    }
}

/*
* 是否可用
* view:视图
*/
func IsViewEnabled(view *FCView)(bool) {
    if view.Enabled {
        pView := view.GetParent()
        if pView.IsNotEmpty {
            if pView.Enabled {
                return IsViewEnabled(pView)
            } else {
                return false
            }
        } else {
            return true
        }
    } else {
        return false
    }
}

/*
* 获取区域的交集
*/
func GetIntersectRect(lpDestRect *FCRect, lpSrc1Rect FCRect, lpSrc2Rect FCRect)(int){
    lpDestRect.Left = math.Max(lpSrc1Rect.Left, lpSrc2Rect.Left)
    lpDestRect.Right = math.Min(lpSrc1Rect.Right, lpSrc2Rect.Right)
    lpDestRect.Top = math.Max(lpSrc1Rect.Top, lpSrc2Rect.Top)
    lpDestRect.Bottom = math.Min(lpSrc1Rect.Bottom, lpSrc2Rect.Bottom)
    if lpDestRect.Right > lpDestRect.Left && lpDestRect.Bottom > lpDestRect.Top {
        return 1
    }else {
        lpDestRect.Left = 0
        lpDestRect.Right = 0
        lpDestRect.Top = 0
        lpDestRect.Bottom = 0
        return 0
    }
}

/*
* 全局刷新方法
* paint:绘图对象
*/
func Invalidate(paint *FCPaint) {
    if(paint.OnInvalidate != nil){
        paint.OnInvalidate(paint)
    }else{
        noneRect := CreateRect(0, 0, 0, 0)
        noneRect.IsNotEmpty = false
	    drawRect := CreateRect(0, 0, (paint.Size.Cx / paint.Ratio / paint.ScaleFactorX), (paint.Size.Cy / paint.Ratio / paint.ScaleFactorY))
	    paint.BeginPaint(drawRect, drawRect)
        if(paint.OnRenderViews != nil){
            paint.OnRenderViews(paint.Views, paint, drawRect)
        }else{
	        RenderViews(paint.Views, paint, drawRect)
        }
	    paint.EndPaint()
        ShowOrHideInput(paint.Views)
    }
}

/*
* 刷新视图方法
* view:视图
*/
func InvalidateView(view *FCView) {
    if(view.GetPaint().OnInvalidateView != nil){
        view.GetPaint().OnInvalidateView(view)
    }else{
        if(IsPaintVisible(view)){
		    paint := view.GetPaint()
		    clX := ClientX(view)
		    clY := ClientY(view)
		    drawRect := CreateRect(clX, clY, clX + view.Size.Cx, clY + view.Size.Cy)
		    drawViews := paint.Views
		    allRect := CreateRect(0, 0, (paint.Size.Cx / paint.ScaleFactorX), (paint.Size.Cy / paint.ScaleFactorY))
		    paint.BeginPaint(allRect, drawRect)
            if(view.GetPaint().OnRenderViews != nil){
                view.GetPaint().OnRenderViews(drawViews, paint, drawRect)
            }else{
	            RenderViews(drawViews, paint, drawRect)
            }
		    paint.EndPaint()
            ShowOrHideInput(paint.Views)
        }
    }
}

/*
* 更新悬浮状态
* views:视图集合
*/
func UpdateViewDefault(views []*FCView) {
    if len(views) > 0{
        for i := 0; i < len(views); i++ {
            view := views[i]
            pView := view.GetParent()
            leftStr, ok := view.ExAttributes["leftstr"]
            if ok{
                pWidth := view.GetPaint().Size.Cx / view.GetPaint().ScaleFactorX
                if (pView.IsNotEmpty){
                    pWidth = pView.Size.Cx
                }
                leftStr = strings.Replace(leftStr, "%", "", -1)
                view.Location.X = ConvertToFloat64(leftStr) * pWidth / 100
            }
            topStr, ok2 := view.ExAttributes["topstr"]
            if ok2{
                pHeight := view.GetPaint().Size.Cy / view.GetPaint().ScaleFactorY
                if (pView.IsNotEmpty){
                    pHeight = pView.Size.Cy
                }
                topStr = strings.Replace(topStr, "%", "", -1)
                view.Location.Y = ConvertToFloat64(topStr) * pHeight / 100
            }
            widthStr, ok3 := view.ExAttributes["widthstr"]
            if ok3{
                pWidth := view.GetPaint().Size.Cx / view.GetPaint().ScaleFactorX
                if (pView.IsNotEmpty){
                    pWidth = pView.Size.Cx
                }
                widthStr = strings.Replace(widthStr, "%", "", -1)
                view.Size.Cx = ConvertToFloat64(widthStr) * pWidth / 100
            }
            heightStr, ok4 := view.ExAttributes["heightstr"]
            if ok4{
                pHeight := view.GetPaint().Size.Cy / view.GetPaint().ScaleFactorY
                if (pView.IsNotEmpty){
                    pHeight = pView.Size.Cy
                }
                heightStr = strings.Replace(heightStr, "%", "", -1)
                view.Size.Cy = ConvertToFloat64(heightStr) * pHeight / 100
            }
            if pView.IsNotEmpty && pView.ViewType != "split" {
                margin := view.Margin
			    padding := pView.Padding
                if view.Dock == "fill" {
                    view.Location = CreatePoint(margin.Left + padding.Left, margin.Top + padding.Top)
                    vcx := pView.Size.Cx - margin.Left - padding.Left - margin.Right - padding.Right
                    if vcx < 0{
                        vcx = 0
                    }
                    vcy := pView.Size.Cy - margin.Top - padding.Top - margin.Bottom - padding.Bottom
                    if vcy < 0{
                        vcy = 0
                    }
                    view.Size = CreateSize(vcx, vcy)
                } else if view.Dock == "left" {
                    view.Location = CreatePoint(margin.Left + padding.Left, margin.Top + padding.Top)
                    vcy := pView.Size.Cy - margin.Top - padding.Top - margin.Bottom - padding.Bottom
                    if vcy < 0{
                        vcy = 0
                    }
                    view.Size = CreateSize(view.Size.Cx, vcy)
                } else if view.Dock == "top" {
                    view.Location = CreatePoint(margin.Left + padding.Left, margin.Top + padding.Top)
                    vcx := pView.Size.Cx - margin.Left - padding.Left - margin.Right - padding.Right
                    if vcx < 0{
                        vcx = 0
                    }
                    view.Size = CreateSize(vcx, view.Size.Cy)
                } else if view.Dock == "right" {
                    view.Location = CreatePoint(pView.Size.Cx - view.Size.Cx - padding.Right - margin.Right, margin.Top + padding.Top)
                    vcy := pView.Size.Cy - margin.Top - padding.Top - margin.Bottom - padding.Bottom
                    if vcy < 0{
                        vcy = 0
                    }
                    view.Size = CreateSize(view.Size.Cx, vcy)
                } else if view.Dock == "bottom" {
                    view.Location = CreatePoint(margin.Left + padding.Left, pView.Size.Cy - view.Size.Cy - margin.Bottom - padding.Bottom)
                    vcx := pView.Size.Cx - margin.Left - padding.Left - margin.Right - padding.Right
                    if vcx < 0{
                        vcx = 0
                    }
                    view.Size = CreateSize(vcx, view.Size.Cy)
                }
                if view.Align == "center" {
                    view.Location = CreatePoint((pView.Size.Cx - view.Size.Cx) / 2, view.Location.Y)
                }else if view.Align == "right"{
                    view.Location = CreatePoint(pView.Size.Cx - view.Size.Cx - padding.Right - margin.Right, view.Location.Y)
                }
                if view.VerticalAlign == "middle" {
                    view.Location = CreatePoint(view.Location.X, (pView.Size.Cy - view.Size.Cy) / 2)
                }else if view.VerticalAlign == "bottom"{
                    view.Location = CreatePoint(view.Location.X, pView.Size.Cy - view.Size.Cy - padding.Bottom - margin.Bottom)
                }
            }else if !pView.IsNotEmpty{
                if view.Dock == "fill"{
				    view.Size = CreateSize(view.GetPaint().Size.Cx / view.GetPaint().ScaleFactorX, view.GetPaint().Size.Cy / view.GetPaint().ScaleFactorY)
                }
            }
            if view.ViewType == "split" {
                ResetSplitLayoutDiv(view)
            } else if view.ViewType == "tabview"{
                UpdateTabLayout(view)
            } else if view.ViewType == "layout" {
                ResetLayoutDiv(view)
            } else if view.ViewType == "calendar" {
                UpdateCalendar(view)
            } else if view.ViewType == "chart"{
                chart := view
                inChart := chart.GetChart()         
                ResetChartVisibleRecord(chart)
                CheckChartLastVisibleIndex(chart)
                if inChart.OnCalculateChartMaxMin != nil{
                    inChart.OnCalculateChartMaxMin(chart)
                }else if chart.GetPaint().OnCalculateChartMaxMin != nil{
                    chart.GetPaint().OnCalculateChartMaxMin(chart)
                }else{
                    CalculateChartMaxMin(chart)
                }
            }
            if len(view.Views) > 0 {
                UpdateViewDefault(view.Views)
            }
        }
    }
}


/*
* 视图尺寸改变
*/
func WindowResize(oldRect FCRect, resizePoint int, nowPoint FCPoint, startTouchPoint FCPoint)(FCRect){
    rect := CreateRect(oldRect.Left, oldRect.Top, oldRect.Right, oldRect.Bottom)
	if resizePoint == 0{
		rect.Left = rect.Left + nowPoint.X - startTouchPoint.X;
		rect.Top = rect.Top + nowPoint.Y - startTouchPoint.Y;
	}else if resizePoint == 1{
		rect.Left = rect.Left + nowPoint.X - startTouchPoint.X;
		rect.Bottom = rect.Bottom + nowPoint.Y - startTouchPoint.Y;
	}else if resizePoint == 2{
		rect.Right = rect.Right + nowPoint.X - startTouchPoint.X;
		rect.Top = rect.Top + nowPoint.Y - startTouchPoint.Y;
	}else if resizePoint == 3{
		rect.Right = rect.Right + nowPoint.X - startTouchPoint.X;
		rect.Bottom = rect.Bottom + nowPoint.Y - startTouchPoint.Y;
	}else if resizePoint == 4{
		rect.Left = rect.Left + nowPoint.X - startTouchPoint.X;
	}else if resizePoint == 5{
		rect.Top = rect.Top + nowPoint.Y - startTouchPoint.Y;
	}else if resizePoint == 6{
		rect.Right = rect.Right + nowPoint.X - startTouchPoint.X;
	}else if resizePoint == 7{
		rect.Bottom = rect.Bottom + nowPoint.Y - startTouchPoint.Y;
	}
    return rect;
}

/*
* 获取调整尺寸的点
*/
func GetResizeState(view *FCView, mp FCPoint)(int){
	bWidth := 5.0;
	width := view.Size.Cx;
    height := view.Size.Cy;
	if (mp.X >= 0 && mp.X <= bWidth * 2 && mp.Y >= 0 && mp.Y <= bWidth * 2){
		return 0;
	}else if (mp.X >= 0 && mp.X <= bWidth * 2 && mp.Y >= height - bWidth * 2 && mp.Y <= height){
		return 1;
	}else if (mp.X >= width - bWidth * 2 && mp.X <= width && mp.Y >= 0 && mp.Y <= bWidth * 2){
		return 2;
	}else if (mp.X >= width - bWidth * 2 && mp.X <= width && mp.Y >= height - bWidth * 2 && mp.Y <= height){
		return 3;
	}else if (mp.X >= 0 && mp.X <= bWidth && mp.Y >= 0 && mp.Y <= height){
		return 4;
	}else if (mp.X >= 0 && mp.X <= width && mp.Y >= 0 && mp.Y <= bWidth){
		return 5;
	}else if (mp.X >= width - bWidth && mp.X <= width && mp.Y >= 0 && mp.Y <= height){
		return 6;
	}else if (mp.X >= 0 && mp.X <= width && mp.Y >= height - bWidth && mp.Y <= height){
		return 7;
	}else{
		return -1;
	}
}

/*
* 重绘复选按钮
* checkBox:视图
* paint:绘图对象
* clipRect:裁剪区域
*/
func DrawCheckBox(checkBox *FCView, paint *FCPaint, clipRect FCRect){
    inCheckBox := checkBox.GetCheckBox()
    width := checkBox.Size.Cx
    height := checkBox.Size.Cy
    if checkBox.TextColor != "none" {
        eRight := inCheckBox.ButtonSize.Cx + 10
        eRect := CreateRect(1, (height - inCheckBox.ButtonSize.Cy) / 2, inCheckBox.ButtonSize.Cx + 1, (height + inCheckBox.ButtonSize.Cy) / 2)
        if len(checkBox.Text) == 0{
            eRect = CreateRect((width - inCheckBox.ButtonSize.Cx) / 2, (height - inCheckBox.ButtonSize.Cy) / 2, (width + inCheckBox.ButtonSize.Cx) / 2, (height + inCheckBox.ButtonSize.Cy) / 2)
        }
        paint.DrawRect(checkBox.TextColor, 1, 0, eRect.Left, eRect.Top, eRect.Right, eRect.Bottom)
        if inCheckBox.Checked {
            eRect.Left += 2
            eRect.Top += 2
            eRect.Right -= 2
            eRect.Bottom -= 2
            var drawPoints []FCPoint
		    drawPoints = append(drawPoints, CreatePoint(eRect.Left, eRect.Top + 8))
		    drawPoints = append(drawPoints, CreatePoint(eRect.Left + 6, eRect.Bottom))
		    drawPoints = append(drawPoints, CreatePoint(eRect.Right - 1, eRect.Top))
		    paint.DrawPolyline(checkBox.TextColor, 1, 0, drawPoints)
        }
        if len(checkBox.Text) > 0{
            tSize := paint.TextSize(checkBox.Text, checkBox.Font)
            paint.DrawText(checkBox.Text, checkBox.TextColor, checkBox.Font, eRight, (height - tSize.Cy) / 2)
        }
    }
}

/*
* 重绘单选按钮
* radioButton:视图
* paint:绘图对象
* clipRect:裁剪区域
*/
func DrawRadioButton(radioButton *FCView, paint *FCPaint, clipRect FCRect) {
    inRadioButton := radioButton.GetRadioButton()
    height := radioButton.Size.Cy
    if radioButton.TextColor != "none" {
        eRight := inRadioButton.ButtonSize.Cx + 10
        eRect := CreateRect(1, (height - inRadioButton.ButtonSize.Cy) / 2, inRadioButton.ButtonSize.Cx + 1, (height + inRadioButton.ButtonSize.Cy) / 2)
        paint.DrawEllipse(radioButton.TextColor, 1, 0, eRect.Left, eRect.Top, eRect.Right, eRect.Bottom)
        if inRadioButton.Checked {
            eRect.Left += 2
            eRect.Top += 2
            eRect.Right -= 3
            eRect.Bottom -= 3
            paint.FillEllipse(radioButton.TextColor, eRect.Left, eRect.Top, eRect.Right + 1, eRect.Bottom + 1)
        }
        tSize := paint.TextSize(radioButton.Text, radioButton.Font)
        paint.DrawText(radioButton.Text, radioButton.TextColor, radioButton.Font, eRight, (height - tSize.Cy) / 2)
    }
}

/*
* 重绘按钮
* button:视图
* paint:绘图对象
* clipRect:裁剪区域
*/
func DrawButton(button *FCView, paint *FCPaint, clipRect FCRect) {
    if button == paint.GetTouchDownView() {
        if button.PushedColor != "none" {
            paint.FillRoundRect(button.PushedColor, 0, 0, button.Size.Cx, button.Size.Cy, button.CornerRadius)
        } else if button.BackColor != "none" {
            paint.FillRoundRect(button.BackColor, 0, 0, button.Size.Cx, button.Size.Cy, button.CornerRadius)
        }
    } else if button == paint.GetTouchMoveView() {
        if button.HoveredColor != "none" {
            paint.FillRoundRect(button.HoveredColor, 0, 0, button.Size.Cx, button.Size.Cy, button.CornerRadius)
        } else if button.BackColor != "none" {
            paint.FillRoundRect(button.BackColor, 0, 0, button.Size.Cx, button.Size.Cy, button.CornerRadius)
        }
    } else if button.BackColor != "none"{
        paint.FillRoundRect(button.BackColor, 0, 0, button.Size.Cx, button.Size.Cy, button.CornerRadius)
    }
    if button.TextColor != "none" && len(button.Text) > 0 {
        tSize := paint.TextSize(button.Text, button.Font)
        paint.DrawText(button.Text, button.TextColor, button.Font, (button.Size.Cx - tSize.Cx) / 2, (button.Size.Cy - tSize.Cy) / 2)
    }
    if button.BorderColor != "none" {
        paint.DrawRoundRect(button.BorderColor, button.BorderWidth, 0, 0, 0, button.Size.Cx, button.Size.Cy, button.CornerRadius)
    }
}

/*
* 点击复选按钮
* checkBox:视图
* mp:坐标
*/
func ClickCheckBox(checkBox *FCView, mp FCPoint) {
    inCheckBox := checkBox.GetCheckBox()
    inCheckBox.Checked = !inCheckBox.Checked
}

/*
* 点击单选按钮
* radioButton:视图
* mp: 坐标
*/
func ClickRadioButton(radioButton *FCView, mp FCPoint) {
    inRadioButton := radioButton.GetRadioButton()
    if radioButton.GetParent().IsNotEmpty && len(radioButton.GetParent().Views) > 0 {
        for i := 0; i < len(radioButton.GetParent().Views); i++ {
            rView := radioButton.GetParent().Views[i]
            if rView.ViewType == "radiobutton"{
                rButton := rView
                if rView != radioButton &&
                        rButton.GetRadioButton().GroupName == inRadioButton.GroupName {
                    rButton.GetRadioButton().Checked = false
                }
            }
        }
    }
    inRadioButton.Checked = true
}

/*
* 获取月的日数
* year:年
* month:月
*/
func GetDaysInMonth(year int, month int)(int) {
    switch month {
        case 1:
            return 31
        case 3:
            return 31
        case 5:
            return 31
        case 7:
            return 31
        case 8:
            return 31
        case 10:
            return 31
        case 12:
            return 31
        case 4:
            return 30
        case 6:
            return 30
        case 9:
            return 30
        case 11:
            return 30
        case 2:
            if ((year % 4 == 0 && year % 100 != 0) || year % 400 == 0){
                    return 29
            }else{
                    return 28
            }
    default:
        return 0
    }
}

/*
* 根据字符获取月份
* month:月
*/
func GetMonthStr(month int)(string){
    switch month {
        case 1:
            return "一月"
        case 2:
            return "二月"
        case 3:
            return "三月"
        case 4:
            return "四月"
        case 5:
            return "五月"
        case 6:
            return "六月"
        case 7:
            return "七月"
        case 8:
            return "八月"
        case 9:
            return "九月"
        case 10:
            return "十月"
        case 11:
            return "十一月"
        case 12:
            return "十二月"
        default:
            return ""
    }
}

/*
* 获取年
* years:年的集合
* year:年
*/
func GetYear(calendar *FCView, year int)(*CYear){
    inCalendar := calendar.GetCalendar()
    cy := CreateCYear()
    cy.IsNotEmpty = false
    _, ok := inCalendar.Years[year]
    if ok {
        cy = inCalendar.Years[year]
    }else {
        cy.IsNotEmpty = true
        cy.Year = year
        inCalendar.Years[year] = cy
        for i := 1; i <= 12; i++ {
            cMonth := CreateCMonth()
            cMonth.Year = year
            cMonth.Month = i
            daysInMonth := GetDaysInMonth(year, i)
            for j := 1; j <= daysInMonth; j++ {
                cDay := CreateCDay()
                cDay.Year = year
                cDay.Month = i
                cDay.Day = j
                cMonth.Days[j] = cDay
            }
            cy.Months[i] = cMonth
        } 
    }
    return cy
}

/*
* 显示隐藏日期层
* dayDiv:日期层
* visible:是否可见
*/
func ShowOrHideDayDiv(dayDiv *DayDiv, visible bool) {
    dayButtonSize := len(dayDiv.DayButtons)
    for i := 0; i < dayButtonSize; i++ {
        dayButton := dayDiv.DayButtons[i]
        dayButton.Visible = visible
    }
}

/*
* 显示隐藏月层
* monthDiv:月层
* visible:是否可见
*/
func ShowOrHideMonthDiv(monthDiv *MonthDiv, visible bool) {
    monthButtonSize := len(monthDiv.MonthButtons)
    for i := 0; i < monthButtonSize; i++ {
        monthButton := monthDiv.MonthButtons[i]
        monthButton.Visible = visible
    }
}

/*
* 显示隐藏年层
* yearButtons:年层
* visible:是否可见
*/
func ShowOrHideYearDiv(yearDiv *YearDiv, visible bool) {
    yearButtonSize := len(yearDiv.YearButtons)
    for i := 0; i < yearButtonSize; i++ {
        yearButton := yearDiv.YearButtons[i]
        yearButton.Visible = visible
    }
}

/*
* 初始化日历
* calendar:日历
*/
func InitCalendar(calendar *FCView) {
    inCalendar := calendar.GetCalendar()
    dayDiv := CreateDayDiv()
    monthDiv := CreateMonthDiv()
    yearDiv := CreateYearDiv()
    headDiv := CreateHeadDiv()
    timeDiv := CreateTimeDiv()
    inCalendar.SetDayDiv(dayDiv)
    inCalendar.SetMonthDiv(monthDiv)
    inCalendar.SetYearDiv(yearDiv)
    inCalendar.SetHeadDiv(headDiv)
    inCalendar.SetTimeDiv(timeDiv)
    
    for i := 0; i < 42; i++ {
        dayButton := CreateDayButton()
        dayDiv.DayButtons = append(dayDiv.DayButtons, dayButton)
        dayFCButtonm := CreateDayButton()
        dayFCButtonm.Visible = false
        dayDiv.DayButtonsAm = append(dayDiv.DayButtonsAm, dayFCButtonm)
    }
    for i := 0; i < 42; i++ {
        monthButton := CreateMonthButton()
        monthButton.Month = (i + 1)
        monthDiv.MonthButtons = append(monthDiv.MonthButtons, monthButton)
        monthButtonAm := CreateMonthButton()
        monthButtonAm.Visible = false
        monthButtonAm.Month = (i + 1)
        monthDiv.MonthButtonsAm = append(monthDiv.MonthButtonsAm, monthButtonAm)
    }
    for i := 0; i < 42; i++ {
        yearButton := CreateYearButton()
        yearDiv.YearButtons = append(yearDiv.YearButtons, yearButton)
        yearButtonAm := CreateYearButton()
        yearButtonAm.Visible = false
        yearDiv.YearButtonsAm = append(yearDiv.YearButtonsAm, yearButtonAm)
    }
}

/*
* 获取星期
* y:年
* m:月
* d:日
*/
func DayOfWeek(y int, m int, d int)(int) {
    mm := m
    yy := y
    if mm == 1 || mm == 2 {
       mm += 12
       yy -= 1
   }
   return int(((d + 2 * mm + 3 * (mm + 1) / 5 + yy + yy / 4 - yy / 100 + yy / 400) + 1) % 7)
}

/*
* 获取当月
* calendar:日历
*/
func GetMonth(calendar *FCView)(*CMonth) {
    inCalendar := calendar.GetCalendar()
    cYear := GetYear(calendar, inCalendar.GetSelectedDay().Year)
    cMonth := cYear.Months[inCalendar.GetSelectedDay().Month]
    return cMonth
}

/*
* 获取下个月
* calendar:日历
* year:年
* month:月
*/
func GetNextMonth(calendar *FCView, year int, month int)(*CMonth) {
    nextMonth := month + 1
    nextYear := year
    if nextMonth == 13 {
      nextMonth = 1
      nextYear += 1
    }
    return GetYear(calendar, nextYear).Months[nextMonth]
}

/*
* 获取上个月
* calendar:日历
* year:年
* month:月
*/
func GetLastMonth(calendar *FCView, year int, month int)(*CMonth) {
    lastMonth := month - 1
    lastYear := year
    if lastMonth == 0 {
        lastMonth = 12
        lastYear -= 1
    }
    return GetYear(calendar, lastYear).Months[lastMonth]
}

/*
* 重置日期层布局
* calendar:日历
* dayDiv:日期层
* state:状态
*/
func ResetDayDiv(calendar *FCView, dayDiv *DayDiv, state int) {
    inCalendar := calendar.GetCalendar()
    thisMonth := GetMonth(calendar)
    lastMonth := GetLastMonth(calendar, thisMonth.Year, thisMonth.Month)
    nextMonth := GetNextMonth(calendar, thisMonth.Year, thisMonth.Month)
    left := 0.0
    headHeight := inCalendar.GetHeadDiv().Bounds.Bottom
    top := headHeight
    width := calendar.Size.Cx
    height := calendar.Size.Cy
    height -= inCalendar.GetTimeDiv().Bounds.Bottom - inCalendar.GetTimeDiv().Bounds.Top
    dayButtonHeight := height - headHeight
    if dayButtonHeight < 1 {
        dayButtonHeight = 1
    }
    toY := 0.0
    if dayDiv.ADirection == 1 {
        toY = dayButtonHeight * float64(dayDiv.ATick) / float64(dayDiv.ATotalTick)
        if state == 1 {
            thisMonth = nextMonth
            month := thisMonth.Month
            lastMonth = GetLastMonth(calendar, thisMonth.Year, month)
            nextMonth = GetNextMonth(calendar, thisMonth.Year, month)
        }
    }else if dayDiv.ADirection == 2 {
        toY = -dayButtonHeight * float64(dayDiv.ATick) / float64(dayDiv.ATotalTick)
        if state == 1 {
            thisMonth = lastMonth
            month := thisMonth.Month
            lastMonth = GetLastMonth(calendar, thisMonth.Year, month)
            nextMonth = GetNextMonth(calendar, thisMonth.Year, month)
        }
    }
    buttonSize := 0
    if state == 0 {
        buttonSize = len(dayDiv.DayButtons)
    } else if (state == 1) {
        buttonSize = len(dayDiv.DayButtonsAm)
    }
    dheight := dayButtonHeight / 6
    days := thisMonth.Days
    firstDay := days[1]
    startDayOfWeek := DayOfWeek(firstDay.Year, firstDay.Month, firstDay.Day)
    for i := 0; i < buttonSize; i++ {
        dayButton := new(DayButton)
        if state == 0 {
            dayButton = dayDiv.DayButtons[i]
            buttonSize = len(dayDiv.DayButtons)
        }else if state == 1 {
            dayButton = dayDiv.DayButtonsAm[i]
            buttonSize = len(dayDiv.DayButtonsAm)
        }
        if i == 35 {
            dheight = height - top
        }
        vOffset := 0.0
        if state == 1 {
            if dayDiv.ATick > 0 {
                dayButton.Visible = true
                if dayDiv.ADirection == 1 {
                    vOffset = toY - dayButtonHeight
                } else if dayDiv.ADirection == 2 {
                    vOffset = toY + dayButtonHeight

                }
            }else {
                dayButton.Visible = false
                continue
            }
        }else {
            vOffset = toY
        }
        if (i + 1) % 7 == 0 {
            dp := CreatePoint(left, top + vOffset)
            ds := CreateSize(width - left, dheight)
            bounds := CreateRect(dp.X, dp.Y, dp.X + ds.Cx, dp.Y + ds.Cy)
            dayButton.Bounds = bounds
            left = 0
            if i != 0 && i != buttonSize - 1 {
                top += dheight
            }
        }else {
            dp := CreatePoint(left, top + vOffset)
            ds := CreateSize(width / 7, dheight)
            //let ds = FCSize(cx:width / 7 + Double(((i + 1) % 7) % 2), cy:dheight)
            bounds := CreateRect(dp.X, dp.Y, dp.X + ds.Cx, dp.Y + ds.Cy)
            dayButton.Bounds = bounds
            left += ds.Cx
        }
        cDay := new(CDay)
        dayButton.InThisMonth = false
        if i >= startDayOfWeek && i <= startDayOfWeek + len(days) - 1 {
            cDay = days[i - startDayOfWeek + 1]
            dayButton.InThisMonth = true
        }else if i < startDayOfWeek {
            cDay = lastMonth.Days[len(lastMonth.Days) - startDayOfWeek + i + 1]
        }else if i > startDayOfWeek + len(days) - 1 {
            cDay = nextMonth.Days[i - startDayOfWeek - len(days) + 1]
        }
        dayButton.SetDay(cDay)
        if state == 0 && dayButton.GetDay().IsNotEmpty && dayButton.GetDay() == inCalendar.GetSelectedDay() {
            dayButton.Selected = true
        }else {
            dayButton.Selected = false
        }
    }
}

/*
* 重置月层布局
* calendar:日历
* monthDiv:月层
* state:状态
*/
func ResetMonthDiv(calendar *FCView, monthDiv *MonthDiv, state int) {
    inCalendar := calendar.GetCalendar()
    thisYear := monthDiv.Year
    lastYear := monthDiv.Year - 1
    nextYear := monthDiv.Year + 1
    left := 0.0
    headHeight := inCalendar.GetHeadDiv().Bounds.Bottom
    top := headHeight
    width := calendar.Size.Cx
    height := calendar.Size.Cy
    height -= inCalendar.GetTimeDiv().Bounds.Bottom - inCalendar.GetTimeDiv().Bounds.Top
    monthButtonHeight := height - top
    if monthButtonHeight < 1 {
        monthButtonHeight = 1
    }
    toY := 0.0
    var monthButtons []*MonthButton
    if monthDiv.ADirection == 1 {
        toY = monthButtonHeight * float64(monthDiv.ATick) / float64(monthDiv.ATotalTick)
        if state == 1 {
            thisYear = nextYear
            lastYear = thisYear - 1
            nextYear = thisYear + 1
        }
    }else if monthDiv.ADirection == 2 {
        toY = -monthButtonHeight * float64(monthDiv.ATick) / float64(monthDiv.ATotalTick)
        if state == 1 {
            thisYear = lastYear
            lastYear = thisYear - 1
            nextYear = thisYear + 1
        }
    }
    if state == 0 {
        monthButtons = monthDiv.MonthButtons
    }else if state == 1 {
        monthButtons = monthDiv.MonthButtonsAm
    }
    dheight := monthButtonHeight / 3
    buttonSize := len(monthButtons)
    for i := 0; i < buttonSize; i++ {
        if i == 8 {
            dheight = height - top
        }
        monthButton := monthButtons[i]
        monthButton.Year = thisYear
        vOffSet := 0.0
        if state == 1 {
            if monthDiv.ATick > 0{
                monthButton.Visible = true
                if monthDiv.ADirection == 1 {
                    vOffSet = toY - monthButtonHeight
                }else if monthDiv.ADirection == 2 {
                    vOffSet = toY + monthButtonHeight
                }
            }else {
                monthButton.Visible = false
                continue
            }
        }else {
            vOffSet = toY
        }
        if (i + 1) % 4 == 0 {
            dp := CreatePoint(left, top + vOffSet)
            ds := CreateSize(width - left, dheight)
            bounds := CreateRect(dp.X, dp.Y, dp.X + ds.Cx, dp.Y + ds.Cy)
            monthButton.Bounds = bounds
            left = 0
            if i != 0 && i != buttonSize - 1 {
                top += dheight
            }
        } else {
            dp := CreatePoint(left, top + vOffSet)
            //let ds = FCSize(width / 4 + ((i + 1) % 4) % 2, dheight)
            ds := CreateSize(width / 4, dheight)
            bounds := CreateRect(dp.X, dp.Y, dp.X + ds.Cx, dp.Y + ds.Cy)
            monthButton.Bounds = bounds
            left += ds.Cx
        }
    }
}

/*
* 重置年层布局
* calendar:日历
* yearDiv:年层
* state:状态
*/
func ResetYearDiv(calendar *FCView, yearDiv *YearDiv, state int) {
    inCalendar := calendar.GetCalendar()
    thisStartYear := yearDiv.StartYear
    lastStartYear := yearDiv.StartYear - 12
    nextStartYear := yearDiv.StartYear + 12
    left := 0.0
    headHeight := inCalendar.GetHeadDiv().Bounds.Bottom
    top := headHeight
    width := calendar.Size.Cx
    height := calendar.Size.Cy
    height -= inCalendar.GetTimeDiv().Bounds.Bottom - inCalendar.GetTimeDiv().Bounds.Top
    yearButtonHeight := height - top
    if yearButtonHeight < 1 {
        yearButtonHeight = 1
    }
    toY := 0.0
    var yearButtons []*YearButton
    if yearDiv.ADirection == 1 {
        toY = yearButtonHeight * float64(yearDiv.ATick) / float64(yearDiv.ATotalTick)
        if state == 1 {
            thisStartYear = nextStartYear
            lastStartYear = thisStartYear - 12
            nextStartYear = thisStartYear + 12
        }
    }else if yearDiv.ADirection == 2 {
        toY = -yearButtonHeight * float64(yearDiv.ATick) / float64(yearDiv.ATotalTick)
        if state == 1 {
            thisStartYear = lastStartYear
            lastStartYear = thisStartYear - 12
            nextStartYear = thisStartYear + 12
        }
    }
    if state == 0 {
        yearButtons = yearDiv.YearButtons
    }else if state == 1 {
        yearButtons = yearDiv.YearButtonsAm
    }
    dheight := yearButtonHeight / 3
    buttonSize := len(yearDiv.YearButtons)
    for i := 0; i < buttonSize; i++ {
        if i == 8 {
            dheight = height - top
        }
        yearButton := yearButtons[i]
        yearButton.Year = thisStartYear + i
        vOffSet := 0.0
        if state == 1 {
            if yearDiv.ATick > 0 {
                yearButton.Visible = true
                if yearDiv.ADirection == 1 {
                    vOffSet = toY - yearButtonHeight
                }else if yearDiv.ADirection == 2 {
                    vOffSet = toY + yearButtonHeight
                }
            }else {
                yearButton.Visible = false
                continue
            }
        }else {
            vOffSet = toY
        }
        if (i + 1) % 4 == 0 {
            dp := CreatePoint(left, top + vOffSet)
            ds := CreateSize(width - left, dheight)
            bounds := CreateRect(dp.X, dp.Y, dp.X + ds.Cx, dp.Y + ds.Cy)
            yearButton.Bounds = bounds
            left = 0
            if i != 0 && i != buttonSize - 1 {
                top += dheight
            }
        }else {
            dp := CreatePoint(left, top + vOffSet)
            //let ds = FCSize(width / 4 + ((i + 1) % 4) % 2, dheight)
            ds := CreateSize(width / 4, dheight)
            bounds := CreateRect(dp.X, dp.Y, dp.X + ds.Cx, dp.Y + ds.Cy)
            yearButton.Bounds = bounds
            left += ds.Cx
        }
    }
}

/*
* 选择开始年份
* calendar:日历
* yearDiv:年层
* startYear:开始年
*/
func SelectStartYear(calendar *FCView, yearDiv *YearDiv, startYear int) {
    inCalendar := calendar.GetCalendar()
    if yearDiv.StartYear != startYear {
        if startYear > yearDiv.StartYear {
            yearDiv.ADirection = 1
        } else {
            yearDiv.ADirection = 2
        }
        if inCalendar.UseAnimation {
            yearDiv.ATick = yearDiv.ATotalTick
        }
        yearDiv.StartYear = startYear
    }
}

/*
* 选择年份
* calendar:日历
* monthDiv:月层
* year:年
*/
func SelectYear(calendar *FCView, monthDiv *MonthDiv, year int) {
    inCalendar := calendar.GetCalendar()
    if monthDiv.Year != year {
        if year > monthDiv.Year {
            monthDiv.ADirection = 1
        }else {
            monthDiv.ADirection = 2
        }
        if inCalendar.UseAnimation {
            monthDiv.ATick = monthDiv.ATotalTick
        }
        monthDiv.Year = year
    }
}

/*
* 选中日期
* calendar:日历
* dayDiv:日期层
* selectedDay:选中日
* lastDay:上一日
*/
func SelectDay(calendar *FCView, dayDiv *DayDiv, selectedDay *CDay, lastDay *CDay) {
    inCalendar := calendar.GetCalendar()
    m := GetYear(calendar, selectedDay.Year).Months[selectedDay.Month]
    thisMonth := GetYear(calendar, lastDay.Year).Months[lastDay.Month]
    if m != thisMonth {
        if thisMonth.Year * 12 + thisMonth.Month > m.Year * 12 + m.Month {
            dayDiv.ADirection = 2
        }else {
            dayDiv.ADirection = 1
        }
        buttonSize := len(dayDiv.DayButtons)
        for i := 0; i < buttonSize; i++ {
            dayButton := dayDiv.DayButtons[i]
            if (dayDiv.ADirection == 1 && dayButton.GetDay() == thisMonth.Days[0]) || (dayDiv.ADirection == 2 && dayButton.GetDay() == thisMonth.Days[len(thisMonth.Days) - 1]) {
                dayDiv.AClickRowFrom = int(i / 7)
                if i % 7 != 0{
                    dayDiv.AClickRowFrom += 1
                }
            }
        }
        ResetDayDiv(calendar, dayDiv, 0)
        buttonSize = len(dayDiv.DayButtonsAm)
        for i := 0; i < buttonSize; i++ {
            dayFCButtonm := dayDiv.DayButtonsAm[i]
            if (dayDiv.ADirection == 1 && dayFCButtonm.GetDay() == m.Days[0]) || (dayDiv.ADirection == 2 && dayFCButtonm.GetDay() == m.Days[len(m.Days) - 1]) {
                dayDiv.AClickRowTo = int(i / 7)
                if i % 7 != 0 {
                    dayDiv.AClickRowTo += 1
                }
            }
        }
        if inCalendar.UseAnimation {
            dayDiv.ATick = dayDiv.ATotalTick
        }
    } else {
        dayButtonsSize := len(dayDiv.DayButtons)
        for i := 0; i < dayButtonsSize; i++ {
            dayButton := dayDiv.DayButtons[i]
            if dayButton.GetDay() != selectedDay {
                dayButton.Selected = false
            }
        }
    }
}

/*
* 更新日历的布局
* calendar:日历
*/
func UpdateCalendar(calendar *FCView) {
    inCalendar := calendar.GetCalendar()
    headDiv := inCalendar.GetHeadDiv()
    headDiv.Bounds = CreateRect(0, 0, calendar.Size.Cx, 80)
    if inCalendar.Mode == "day" {
        ResetDayDiv(calendar, inCalendar.GetDayDiv(), 0)
        ResetDayDiv(calendar, inCalendar.GetDayDiv(), 1)
    } else if inCalendar.Mode == "month" {
        ResetMonthDiv(calendar, inCalendar.GetMonthDiv(), 0)
        ResetMonthDiv(calendar, inCalendar.GetMonthDiv(), 1)
    }else if inCalendar.Mode == "year" {
        ResetYearDiv(calendar, inCalendar.GetYearDiv(), 0)
        ResetYearDiv(calendar, inCalendar.GetYearDiv(), 1)
    }
}

/*
* 绘制头部层
* calendar:日历
* headDiv:头部层
* paint:绘图对象
*/
func DrawHeadDiv(calendar *FCView, headDiv *HeadDiv, paint *FCPaint) {
    inCalendar := calendar.GetCalendar()
    bounds := headDiv.Bounds
    if headDiv.BackColor != "none" {
        paint.FillRect(headDiv.BackColor, bounds.Left, bounds.Top, bounds.Right, bounds.Bottom)
    }
    var weekStrings []string
    weekStrings = append(weekStrings, "周日")
    weekStrings = append(weekStrings, "周一")
    weekStrings = append(weekStrings, "周二")
    weekStrings = append(weekStrings, "周三")
    weekStrings = append(weekStrings, "周四")
    weekStrings = append(weekStrings, "周五")
    weekStrings = append(weekStrings, "周六")
    w := bounds.Right - bounds.Left
    left := bounds.Left
    for i := 0; i < 7; i++ {
        weekDaySize := paint.TextSize(weekStrings[i], headDiv.WeekFont)
        textX := left + (w / 7) / 2 - weekDaySize.Cx / 2
        textY := bounds.Bottom - weekDaySize.Cy - 2
        paint.DrawText(weekStrings[i], headDiv.TextColor, headDiv.WeekFont, textX, textY)
        left += w / 7
    }
    drawTitle := ""
    selectedDay := inCalendar.GetSelectedDay()
    if inCalendar.Mode == "day" {
        drawTitle = ToFixed(float64(selectedDay.Year), 0) + "年" + ConvertIntToStr(selectedDay.Month) + "月"
    } else if inCalendar.Mode == "month" {
        monthDiv := inCalendar.GetMonthDiv()
        drawTitle = ToFixed(float64(monthDiv.Year), 0) + "年"
    } else {
        yearDiv := inCalendar.GetYearDiv()
        drawTitle = ToFixed(float64(yearDiv.StartYear), 0) + "年-" + ConvertIntToStr(yearDiv.StartYear + 11) + "年"
    }
    tSize := paint.TextSize(drawTitle, headDiv.TitleFont)
    paint.DrawText(drawTitle, headDiv.TextColor, headDiv.TitleFont, bounds.Left + (w - tSize.Cx) / 2, 30)
    tR := 10.0
    var drawPoints []FCPoint
	drawPoints = append(drawPoints, CreatePoint(5, bounds.Top + (bounds.Bottom - bounds.Top) / 2))
	drawPoints = append(drawPoints, CreatePoint(5 + tR * 2, bounds.Top + (bounds.Bottom - bounds.Top) / 2 - tR))
	drawPoints = append(drawPoints, CreatePoint(5 + tR * 2, bounds.Top + (bounds.Bottom - bounds.Top) / 2 + tR))
	paint.FillPolygon(headDiv.ArrowColor, drawPoints)
	var drawPoints2 []FCPoint
	drawPoints2 = append(drawPoints2, CreatePoint(bounds.Right - 5, bounds.Top + (bounds.Bottom - bounds.Top) / 2))
	drawPoints2 = append(drawPoints2, CreatePoint(bounds.Right - 5 - tR * 2, bounds.Top + (bounds.Bottom - bounds.Top) / 2 - tR))
	drawPoints2 = append(drawPoints2, CreatePoint(bounds.Right - 5 - tR * 2, bounds.Top + (bounds.Bottom - bounds.Top) / 2 + tR))
	paint.FillPolygon(headDiv.ArrowColor, drawPoints2)
}

/*
* 绘制日的按钮
* calendar:日历
* dayButton:日期按钮
* paint:绘图对象
*/
func DrawDayButton(calendar *FCView, dayButton *DayButton, paint *FCPaint) {
    cDay := dayButton.GetDay()
    if cDay.IsNotEmpty {
        bounds := dayButton.Bounds
        text := ConvertIntToStr(cDay.Day)
        if dayButton.BackColor != "none" {
            paint.FillRect(dayButton.BackColor, bounds.Left + 2, bounds.Top + 2, bounds.Right - 2, bounds.Bottom - 2)
        }
        if dayButton.InThisMonth {
            paint.DrawText(text, dayButton.TextColor, dayButton.Font, bounds.Left + 5, bounds.Top + 7)
        } else {
            paint.DrawText(text, dayButton.TextColor2, dayButton.Font, bounds.Left + 5, bounds.Top + 7)
        }
        if dayButton.BorderColor != "none" {
            paint.DrawRect(dayButton.BorderColor, 1, 0, bounds.Left + 2, bounds.Top + 2, bounds.Right - 2, bounds.Bottom - 2)
        }
    }
}

/*
* 绘制月的按钮
* calendar:日历
* monthButton:月按钮
* paint:绘图对象
*/
func DrawMonthButton(calendar *FCView, monthButton *MonthButton, paint *FCPaint) {
    bounds := monthButton.Bounds
    text := GetMonthStr(monthButton.Month)
    if monthButton.BackColor != "none" {
        paint.FillRect(monthButton.BackColor, bounds.Left + 2, bounds.Top + 2, bounds.Right - 2, bounds.Bottom - 2)
    }
    paint.DrawText(text, monthButton.TextColor, monthButton.Font, bounds.Left + 5, bounds.Top + 7)
    if monthButton.BorderColor != "none" {
        paint.DrawRect(monthButton.BorderColor, 1, 0, bounds.Left + 2, bounds.Top + 2, bounds.Right - 2, bounds.Bottom - 2)
    }
}

/*
* 绘制年的按钮
* calendar:日历
* yearButton:年按钮
* paint:绘图对象
*/
func DrawYearButton(calendar *FCView, yearButton *YearButton, paint *FCPaint) {
    bounds := yearButton.Bounds
    text := ConvertIntToStr(yearButton.Year)
    if yearButton.BackColor != "none" {
        paint.FillRect(yearButton.BackColor, bounds.Left + 2, bounds.Top + 2, bounds.Right - 2, bounds.Bottom - 2)
    }
    paint.DrawText(text, yearButton.TextColor, yearButton.Font, bounds.Left + 5, bounds.Top + 7)
    if yearButton.BorderColor != "none" {
        paint.DrawRect(yearButton.BorderColor, 1, 0, bounds.Left + 2, bounds.Top + 2, bounds.Right - 2, bounds.Bottom - 2)
    }
}

/*
* 绘制日历
* calendar:日历
* paint:绘图对象
*/
func DrawCalendar(calendar *FCView, paint *FCPaint) {
    inCalendar := calendar.GetCalendar()
    dayDiv := inCalendar.GetDayDiv()
    monthDiv := inCalendar.GetMonthDiv()
    yearDiv := inCalendar.GetYearDiv()
    if calendar.BackColor != "none" {
        paint.FillRect(calendar.BackColor, 0, 0, calendar.Size.Cx, calendar.Size.Cy)
    }
    if inCalendar.Mode == "day" {
        dayButtonsSize := len(dayDiv.DayButtons)
        for i := 0; i < dayButtonsSize; i++ {
            dayButton := dayDiv.DayButtons[i]
            if dayButton.Visible {
                if inCalendar.OnPaintCalendarDayButton != nil{
                    inCalendar.OnPaintCalendarDayButton(calendar, dayButton, paint)
                }else if paint.OnPaintCalendarDayButton != nil{
                    paint.OnPaintCalendarDayButton(calendar, dayButton, paint)
                }else{
                    DrawDayButton(calendar, dayButton, paint)
                }
            }
        }
        dayFCButtonmSize := len(dayDiv.DayButtonsAm)
        for i := 0; i < dayFCButtonmSize; i++ {
            dayButton := dayDiv.DayButtonsAm[i]
            if dayButton.Visible {
                if inCalendar.OnPaintCalendarDayButton != nil{
                    inCalendar.OnPaintCalendarDayButton(calendar, dayButton, paint)
                }else if paint.OnPaintCalendarDayButton != nil{
                    paint.OnPaintCalendarDayButton(calendar, dayButton, paint)
                }else{
                    DrawDayButton(calendar, dayButton, paint)
                }
            }
        }
    }else if inCalendar.Mode == "month" {
        monthButtonsSize := len(monthDiv.MonthButtons)
        for i := 0; i < monthButtonsSize; i++ {
            monthButton := monthDiv.MonthButtons[i]
            if monthButton.Visible {
                if inCalendar.OnPaintCalendarMonthButton != nil{
                    inCalendar.OnPaintCalendarMonthButton(calendar, monthButton, paint)
                }else if paint.OnPaintCalendarMonthButton != nil{
                    paint.OnPaintCalendarMonthButton(calendar, monthButton, paint)
                }else{
                    DrawMonthButton(calendar, monthButton, paint)
                }
            }
        }
        monthFCButtonmSize := len(monthDiv.MonthButtonsAm)
        for i := 0; i < monthFCButtonmSize; i++ {
            monthButton := monthDiv.MonthButtonsAm[i]
            if monthButton.Visible {
                if inCalendar.OnPaintCalendarMonthButton != nil{
                    inCalendar.OnPaintCalendarMonthButton(calendar, monthButton, paint)
                }else if paint.OnPaintCalendarMonthButton != nil{
                    paint.OnPaintCalendarMonthButton(calendar, monthButton, paint)
                }else{
                    DrawMonthButton(calendar, monthButton, paint)
                }
            }
        }
    } else if inCalendar.Mode == "year" {
        yearButtonsSize := len(yearDiv.YearButtons)
        for i := 0; i < yearButtonsSize; i++ {
            yearButton := yearDiv.YearButtons[i]
            if yearButton.Visible {
                if inCalendar.OnPaintCalendarYearButton != nil{
                    inCalendar.OnPaintCalendarYearButton(calendar, yearButton, paint)
                }else if paint.OnPaintCalendarYearButton != nil{
                    paint.OnPaintCalendarYearButton(calendar, yearButton, paint)
                }else{
                    DrawYearButton(calendar, yearButton, paint)
                }
            }
        }
        yearFCButtonmSize := len(yearDiv.YearButtonsAm)
        for i := 0; i < yearFCButtonmSize; i++ {
            yearButton := yearDiv.YearButtonsAm[i]
            if (yearButton.Visible) {
                if inCalendar.OnPaintCalendarYearButton != nil{
                    inCalendar.OnPaintCalendarYearButton(calendar, yearButton, paint)
                }else if paint.OnPaintCalendarYearButton != nil{
                    paint.OnPaintCalendarYearButton(calendar, yearButton, paint)
                }else{
                    DrawYearButton(calendar, yearButton, paint)
                }
            }
        }
    }
    if inCalendar.OnPaintCalendarHeadDiv != nil{
        inCalendar.OnPaintCalendarHeadDiv(calendar, inCalendar.GetHeadDiv(), paint)
    }else if paint.OnPaintCalendarHeadDiv != nil{
        paint.OnPaintCalendarHeadDiv(calendar, inCalendar.GetHeadDiv(), paint)
    }else{
        DrawHeadDiv(calendar, inCalendar.GetHeadDiv(), paint)
    }
    if calendar.BorderColor != "none" {
        paint.DrawRect(calendar.BorderColor, 1, 0, 0, 0, calendar.Size.Cx, calendar.Size.Cy)
    }
}

/*
* 点击日的按钮
* calendar:日历
* dayButton:日期按钮
* mp:坐标
*/
func ClickDayButton(calendar *FCView, dayButton *DayButton, mp FCPoint) {
    inCalendar := calendar.GetCalendar()
    lastDay := inCalendar.GetSelectedDay()
    inCalendar.SetSelectedDay(dayButton.GetDay())
    SelectDay(calendar, inCalendar.GetDayDiv(), inCalendar.GetSelectedDay(), lastDay)
    UpdateCalendar(calendar)
    InvalidateView(calendar)
}

/*
* 点击月的按钮
* calendar:日历
* monthButton:月按钮
* mp:坐标
*/
func ClickMonthButton(calendar *FCView, monthButton *MonthButton, mp FCPoint) {
    inCalendar := calendar.GetCalendar()
    month := GetYear(calendar, monthButton.Year).Months[monthButton.Month]
    inCalendar.Mode = "day"
    lastDay := inCalendar.GetSelectedDay()
    inCalendar.SetSelectedDay(month.Days[1])
    SelectDay(calendar, inCalendar.GetDayDiv(), inCalendar.GetSelectedDay(), lastDay)
    UpdateCalendar(calendar)
    InvalidateView(calendar)
}

/*
* 点击年的按钮
* calendar:日历
* yearButton:年按钮
* mp:坐标
*/
func ClickYearButton(calendar *FCView, yearButton *YearButton, mp FCPoint) {
    inCalendar := calendar.GetCalendar()
    inCalendar.Mode = "month"
    SelectYear(calendar, inCalendar.GetMonthDiv(), yearButton.Year)
    UpdateCalendar(calendar)
    InvalidateView(calendar)
}

/*
* 点击左侧的按钮
* calendar:日历
* headDiv:头部层
* mp:坐标
*/
func ClickLastButton(calendar *FCView, headDiv *HeadDiv, mp FCPoint) {
    inCalendar := calendar.GetCalendar()
    if inCalendar.Mode == "day"{
        lastMonth := GetLastMonth(calendar, inCalendar.GetSelectedDay().Year, inCalendar.GetSelectedDay().Month)
        lastDay := inCalendar.GetSelectedDay()
        inCalendar.SetSelectedDay(lastMonth.Days[1])
        SelectDay(calendar, inCalendar.GetDayDiv(), inCalendar.GetSelectedDay(), lastDay)
        UpdateCalendar(calendar)
        InvalidateView(calendar)
    } else if inCalendar.Mode == "month" {
        year := inCalendar.GetMonthDiv().Year
        year -= 1
        SelectYear(calendar, inCalendar.GetMonthDiv(), year)
        UpdateCalendar(calendar)
        InvalidateView(calendar)
    } else if inCalendar.Mode == "year" {
        year := inCalendar.GetYearDiv().StartYear
        year -= 12
        SelectStartYear(calendar, inCalendar.GetYearDiv(), year)
        UpdateCalendar(calendar)
        InvalidateView(calendar)
    }
}

/*
* 点击右侧的按钮
* calendar:日历
* headDiv:头部层
* mp:坐标
*/
func ClickNextButton(calendar *FCView, headDiv *HeadDiv, mp FCPoint) {
    inCalendar := calendar.GetCalendar()
    if inCalendar.Mode == "day" {
        nextMonth := GetNextMonth(calendar, inCalendar.GetSelectedDay().Year, inCalendar.GetSelectedDay().Month)
        lastDay := inCalendar.GetSelectedDay()
        inCalendar.SetSelectedDay(nextMonth.Days[1])
        SelectDay(calendar, inCalendar.GetDayDiv(), inCalendar.GetSelectedDay(), lastDay)
        UpdateCalendar(calendar)
        InvalidateView(calendar)
    } else if inCalendar.Mode == "month" {
        year := inCalendar.GetMonthDiv().Year
        year += 1
        SelectYear(calendar, inCalendar.GetMonthDiv(), year)
        UpdateCalendar(calendar)
        InvalidateView(calendar)
    } else if inCalendar.Mode == "year" {
        year := inCalendar.GetYearDiv().StartYear
        year += 12
        SelectStartYear(calendar, inCalendar.GetYearDiv(), year)
        UpdateCalendar(calendar)
        InvalidateView(calendar)
    }
}

/*
* 改变模式的按钮
* calendar:日历
* headDiv:头部层
* mp:坐标
*/
func ClickModeButton(calendar *FCView, headDiv *HeadDiv, mp FCPoint) {
    inCalendar := calendar.GetCalendar()
    monthDiv := inCalendar.GetMonthDiv()
    yearDiv := inCalendar.GetYearDiv()
    if inCalendar.Mode == "day" {
        inCalendar.Mode = "month"
        monthDiv.Month = inCalendar.GetSelectedDay().Month
        monthDiv.Year = inCalendar.GetSelectedDay().Year
        UpdateCalendar(calendar)
       InvalidateView(calendar)
    }else if inCalendar.Mode == "month" {
        inCalendar.Mode = "year"
        SelectStartYear(calendar, yearDiv, monthDiv.Year)
        UpdateCalendar(calendar)
        InvalidateView(calendar)
    }
}

/*
* 点击日历
* calendar:日历
* mp:坐标
*/
func ClickCalendar(calendar *FCView, mp FCPoint) {
    inCalendar := calendar.GetCalendar()
    headDiv := inCalendar.GetHeadDiv()
    dayDiv := inCalendar.GetDayDiv()
    monthDiv := inCalendar.GetMonthDiv()
    yearDiv := inCalendar.GetYearDiv()
    headBounds := headDiv.Bounds
    if mp.X >= headBounds.Left && mp.X <= headBounds.Right && mp.Y >= headBounds.Top && mp.Y <= headBounds.Bottom {
        tR := 10.0
        if mp.X < headBounds.Left + tR * 3 {
            ClickLastButton(calendar, inCalendar.GetHeadDiv(), mp)
            return
        } else if mp.X > headBounds.Right - tR * 3 {
            ClickNextButton(calendar, inCalendar.GetHeadDiv(), mp)
            return
        } else {
            ClickModeButton(calendar, inCalendar.GetHeadDiv(), mp)
            return
        }
    }
    if inCalendar.Mode == "day" {
        dayButtonsSize := len(dayDiv.DayButtons)
        for i := 0; i < dayButtonsSize; i++ {
            dayButton := dayDiv.DayButtons[i]
            if dayButton.Visible {
                bounds := dayButton.Bounds
                if mp.X >= bounds.Left && mp.X <= bounds.Right && mp.Y >= bounds.Top && mp.Y <= bounds.Bottom {
                    ClickDayButton(calendar, dayButton, mp)
                    return
                }
            }
        }
    }else if inCalendar.Mode == "month" {
        monthButtonsSize := len(monthDiv.MonthButtons)
        for i := 0; i < monthButtonsSize; i++ {
            monthButton := monthDiv.MonthButtons[i]
            if monthButton.Visible {
                bounds := monthButton.Bounds
                if mp.X >= bounds.Left && mp.X <= bounds.Right && mp.Y >= bounds.Top && mp.Y <= bounds.Bottom {
                    ClickMonthButton(calendar, monthButton, mp)
                    return
                }
            }
        }
    } else if inCalendar.Mode == "year" {
        yearButtonsSize := len(yearDiv.YearButtons)
        for i := 0; i < yearButtonsSize; i++ {
            yearButton := yearDiv.YearButtons[i]
            if yearButton.Visible {
                bounds := yearButton.Bounds
                if mp.X >= bounds.Left && mp.X <= bounds.Right && mp.Y >= bounds.Top && mp.Y <= bounds.Bottom {
                    ClickYearButton(calendar, yearButton, mp)
                    return
                }
            }
        }
    }
}

/*
* 绘制滚动条
* div:图层
* paint:绘图对象
* clipRect:裁剪区域
*/
func DrawDivScrollBar(div *FCView, paint *FCPaint, clipRect FCRect) {
    div.HScrollIsVisible = false
    div.VScrollIsVisible = false
    //绘制滚动条
    if div.ShowHScrollBar {
        contentWidth := GetDivContentWidth(div)
        if contentWidth > 0 && contentWidth > div.Size.Cx {
            sLeft := div.ScrollH / contentWidth * div.Size.Cx
            sRight := (div.ScrollH + div.Size.Cx) / contentWidth * div.Size.Cx
            if sRight - sLeft < div.ScrollSize {
                sRight = sLeft + div.ScrollSize
            }
            if paint.GetTouchMoveView() == div && (div.HoverScrollHButton || div.DownScrollHButton) {
                paint.FillRect(div.ScrollBarHoveredColor, sLeft, div.Size.Cy - div.ScrollSize, sRight, div.Size.Cy)
            } else {
                paint.FillRect(div.ScrollBarColor, sLeft, div.Size.Cy - div.ScrollSize, sRight, div.Size.Cy)
            }
            div.HScrollIsVisible = true
        }
    }
    if div.ShowVScrollBar {
        contentHeight := GetDivContentHeight(div)
        if contentHeight > 0 && contentHeight > div.Size.Cy {
            sTop := div.ScrollV / contentHeight * div.Size.Cy
            sBottom := sTop + (div.Size.Cy / contentHeight * div.Size.Cy)
            if sBottom - sTop < div.ScrollSize {
                sBottom = sTop + div.ScrollSize
            }
            if paint.GetTouchMoveView() == div && (div.HoverScrollVButton || div.DownScrollVButton) {
                paint.FillRect(div.ScrollBarHoveredColor, div.Size.Cx - div.ScrollSize, sTop, div.Size.Cx, sBottom)
            } else {
                paint.FillRect(div.ScrollBarColor, div.Size.Cx - div.ScrollSize, sTop, div.Size.Cx, sBottom)
            }
            div.VScrollIsVisible = true
        }
    }
}

/*
* 获取内容的宽度
* div:图层
*/
func GetDivContentWidth(div *FCView)(float64) {
    cWidth := 0.0
    if len(div.Views) > 0 {
        for i := 0; i < len(div.Views); i++ {
            if div.Views[i].Visible {
                if (cWidth < div.Views[i].Location.X + div.Views[i].Size.Cx) {
                    cWidth = div.Views[i].Location.X + div.Views[i].Size.Cx
                }
            }
        }
    }
    return cWidth
}

/*
* 获取内容的高度
* div:图层
*/
func GetDivContentHeight(div *FCView)(float64) {
    cHeight := 0.0
    if len(div.Views) > 0 {
        for i := 0; i < len(div.Views); i++ {
            if div.Views[i].Visible {
                if (cHeight < div.Views[i].Location.Y + div.Views[i].Size.Cy) {
                    cHeight = div.Views[i].Location.Y + div.Views[i].Size.Cy
                }
            }
        }
    }
    return cHeight
}

/*
* 图层的鼠标移动方法
* div: 图层
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
*/
func TouchMoveDiv(div *FCView, firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint) {
    div.HoverScrollHButton = false
    div.HoverScrollVButton = false
    paint := div.GetPaint()
    mp := CreatePoint(firstPoint.X, firstPoint.Y)
    if firstTouch {
        if div.ShowHScrollBar || div.ShowVScrollBar {
            if div.DownScrollHButton {
                contentWidth := GetDivContentWidth(div)
                subX := (mp.X - div.StartPoint.X) / div.Size.Cx * contentWidth
                newScrollH := div.StartScrollH + subX
                if newScrollH < 0 {
                    newScrollH = 0
                } else if newScrollH > contentWidth - div.Size.Cx {
                    newScrollH = contentWidth - div.Size.Cx
                }
                div.ScrollH = newScrollH
                paint.CancelClick = true
                return

            } else if div.DownScrollVButton {
                contentHeight := GetDivContentHeight(div)
                subY := (mp.Y - div.StartPoint.Y) / div.Size.Cy * contentHeight
                newScrollV := div.StartScrollV + subY
                if newScrollV < 0 {
                    newScrollV = 0
                } else if newScrollV > contentHeight - div.Size.Cy {
                    newScrollV = contentHeight - div.Size.Cy
                }
                div.ScrollV = newScrollV
                paint.CancelClick = true
                return
            }
        }
        if div.AllowDragScroll {
            contentWidth := GetDivContentWidth(div)
            if contentWidth > div.Size.Cx {
                subX := div.StartPoint.X - mp.X
                newScrollH := div.StartScrollH + subX
                if newScrollH < 0 {
                    newScrollH = 0
                } else if newScrollH > contentWidth - div.Size.Cx{
                    newScrollH = contentWidth - div.Size.Cx
                }
                div.ScrollH = newScrollH
                if subX > 5 || subX < -5 {
                    paint.CancelClick = true
                }
            }
            contentHeight := GetDivContentHeight(div)
            if contentHeight > div.Size.Cy {
                subY := div.StartPoint.Y - mp.Y
                newScrollV := div.StartScrollV + subY
                if newScrollV < 0 {
                    newScrollV = 0
                } else if newScrollV > contentHeight - div.Size.Cy {
                    newScrollV = contentHeight - div.Size.Cy
                }
                div.ScrollV = newScrollV
                if subY > 5 || subY < -5 {
                    paint.CancelClick = true
                }
            }
        }
    } else {
        if div.ShowHScrollBar {
            contentWidth := GetDivContentWidth(div)
            if contentWidth > 0 && contentWidth > div.Size.Cx {
                sLeft := div.ScrollH / contentWidth * div.Size.Cx
                sRight := (div.ScrollH + div.Size.Cx) / contentWidth * div.Size.Cx
                if sRight - sLeft < div.ScrollSize {
                    sRight = sLeft + div.ScrollSize
                }
                if mp.X >= sLeft && mp.X <= sRight && mp.Y >= div.Size.Cy - div.ScrollSize && mp.Y <= div.Size.Cy {
                    div.HoverScrollHButton = true
                    return
                } else {
                    div.HoverScrollHButton = false
                }
            }
        }
        if div.ShowVScrollBar {
            contentHeight := GetDivContentHeight(div)
            if contentHeight > 0 && contentHeight > div.Size.Cy{
                sTop := div.ScrollV / contentHeight * div.Size.Cy
                sBottom := (div.ScrollV + div.Size.Cy) / contentHeight * div.Size.Cy
                if sBottom - sTop < div.ScrollSize {
                    sBottom = sTop + div.ScrollSize
                }
                if mp.X >= div.Size.Cx - div.ScrollSize && mp.X <= div.Size.Cx && mp.Y >= sTop && mp.Y <= sBottom{
                    div.HoverScrollVButton = true
                    return
                } else {
                    div.HoverScrollVButton = false
                }
            }
        }
    }
}

/*
* 图层的鼠标按下方法
* div: 图层
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
* clicks:点击次数
*/
func TouchDownDiv(div *FCView, firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint, clicks int) {
    mp := CreatePoint(firstPoint.X, firstPoint.Y)
    div.StartPoint = mp
    div.DownScrollHButton = false
    div.DownScrollVButton = false
    div.HoverScrollHButton = false
    div.HoverScrollVButton = false
    if div.ShowHScrollBar {
        contentWidth := GetDivContentWidth(div)
        if contentWidth > 0 && contentWidth > div.Size.Cx {
            sLeft := div.ScrollH / contentWidth * div.Size.Cx
            sRight := (div.ScrollH + div.Size.Cx) / contentWidth * div.Size.Cx
            if sRight - sLeft < div.ScrollSize {
                sRight = sLeft + div.ScrollSize
            }
            if mp.X >= sLeft && mp.X <= sRight && mp.Y >= div.Size.Cy - div.ScrollSize && mp.Y <= div.Size.Cy {
                div.DownScrollHButton = true
                div.StartScrollH = div.ScrollH
                return
            }
        }
    }
    if div.ShowVScrollBar {
        contentHeight := GetDivContentHeight(div)
        if contentHeight > 0 && contentHeight > div.Size.Cy {
            sTop := div.ScrollV / contentHeight * div.Size.Cy
            sBottom := (div.ScrollV + div.Size.Cy) / contentHeight * div.Size.Cy
            if sBottom - sTop < div.ScrollSize{
                sBottom = sTop + div.ScrollSize
            }
            if mp.X >= div.Size.Cx - div.ScrollSize && mp.X <= div.Size.Cx && mp.Y >= sTop && mp.Y <= sBottom {
                div.DownScrollVButton = true
                div.StartScrollV = div.ScrollV
                return
            }
        }
    }
    if div.AllowDragScroll {
        div.StartScrollH = div.ScrollH
        div.StartScrollV = div.ScrollV
    }
}

/*
* 图层的鼠标抬起方法
* div: 图层
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
* clicks:点击次数
*/
func TouchUpDiv(div *FCView, firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint, clicks int) {
    div.HoverScrollHButton = false
    div.HoverScrollVButton = false
    div.DownScrollHButton = false
    div.DownScrollVButton = false
}

/*
* 图层的鼠标滚轮方法
* div:图层
* delta:滚轮值
*/
func TouchWheelDiv(div *FCView, delta int) {
    oldScrollV := div.ScrollV
    if delta < 0 {
        oldScrollV -= 20
    } else if delta > 0 {
        oldScrollV += 20
    }
    contentHeight := GetDivContentHeight(div)
    if contentHeight < div.Size.Cy {
        div.ScrollV = 0
    } else {
        if oldScrollV < 0{
            oldScrollV = 0
        } else if oldScrollV > contentHeight - div.Size.Cy {
            oldScrollV = contentHeight - div.Size.Cy
        }
        div.ScrollV = oldScrollV
    }
}

/*
* 重绘图层
* div:视图
* paint:绘图对象
* clipRect:裁剪区域
*/
func DrawDiv(div *FCView, paint *FCPaint, clipRect FCRect) {
    if div.BackColor != "none" {
        paint.FillRoundRect(div.BackColor, 0, 0, div.Size.Cx, div.Size.Cy, div.CornerRadius)
    }
}

/*
 * 快速添加表格列
 * grid:表格
 * columns:列名集合
 */
func FastAddGridColumns(grid *FCView, columns []string){
    inGrid := grid.GetGrid()
    columnsSize := len(columns)
    for i := 0; i < columnsSize; i++ {
        gridColumn := CreateGridColumn()
        gridColumn.Text = columns[i]
        inGrid.Columns = append(inGrid.Columns, gridColumn)
    }
}

/*
 * 快速添加表格行
 * grid:表格
 * datas:数据集合
 */
func FastAddGridRow(grid *FCView, datas []string)(*FCGridRow) {
    gridRow := CreateGridRow()
    datasSize := len(datas)
    for i := 0; i < datasSize; i++ {
        gridCell := CreateGridCell()
        gridCell.Value = datas[i]
        gridRow.Cells = append(gridRow.Cells, gridCell)
    }
    return gridRow
}

/*
 * 添加视图到单元格
 * view:视图
 * cell:单元格
 * grid:表格
 */
func AddViewToGridCell(view *FCView, cell *FCGridCell, grid *FCView){
    view.DisplayOffset = false
    view.Visible = false
    cell.SetView(view)
    AddViewToParent(view, grid)
}

/*
* 重绘图层边线
* div:视图
* paint:绘图对象
* clipRect:裁剪区域
*/
func DrawDivBorder(div *FCView, paint *FCPaint, clipRect FCRect) {
    if div.BorderColor != "none" {
        paint.DrawRoundRect(div.BorderColor, div.BorderWidth, 0, 0, 0, div.Size.Cx, div.Size.Cy, div.CornerRadius)
    }
}

/*
* 绘制单元格
* grid:表格
* row:行
* column:列
* cell:单元格
* paint:绘图对象
* left:左侧坐标
* top:上方坐标
* right:右侧坐标
* bottom:下方坐标
*/
func DrawGridCell(grid *FCView, row *FCGridRow, column *FCGridColumn, cell *FCGridCell, paint *FCPaint, left float64, top float64, right float64, bottom float64) {
    inGrid := grid.GetGrid()    
    if cell.BackColor != "none" {
        paint.FillRect(cell.BackColor, left, top, right, bottom)
    }
    if row.Selected{
        if inGrid.SelectedRowColor != "none" {
            paint.FillRect(inGrid.SelectedRowColor, left, top, right, bottom)
        }
    }
    if cell.BorderColor != "none" {
        //paint.DrawRect(cell.BorderColor, 1, 0, left, top, right, bottom)
        paint.DrawRect(cell.BorderColor, 1, 0, left, bottom, right, bottom)
		paint.DrawRect(cell.BorderColor, 1, 0, right - 1, top, right - 1, bottom)
    }
    if len(cell.Value) > 0 {
        showText := cell.Value
        if (column.ColType == "double") {
			if (cell.Digit >= 0) {
				numValue := ConvertToFloat64(showText)
				showText = ToFixed(numValue, cell.Digit)
			}
		}
        tSize := paint.TextSize(showText, cell.Font)
        if tSize.Cx > right - left{
            paint.DrawTextAutoEllipsis(showText, cell.TextColor, cell.Font, left + 2, top + inGrid.RowHeight / 2 - tSize.Cy / 2, right - 2, top + inGrid.RowHeight / 2 + tSize.Cy / 2)
        }else{
            if column.CellAlign == "left"{
                paint.DrawText(showText, cell.TextColor, cell.Font, left + 2, top + inGrid.RowHeight / 2 - tSize.Cy / 2)
            }else if column.CellAlign == "center"{
                paint.DrawText(showText, cell.TextColor, cell.Font, left + (right - left - tSize.Cx) / 2, top + inGrid.RowHeight / 2 - tSize.Cy / 2)
            }else if column.CellAlign == "right"{
                paint.DrawText(showText, cell.TextColor, cell.Font, right - tSize.Cx, top + inGrid.RowHeight / 2 - tSize.Cy / 2)
            }
        }
    }
}

/*
* 绘制列
* grid:表格
* column:列
* paint:绘图对象
* left:左侧坐标
* top:上方坐标
* right:右侧坐标
* bottom:下方坐标
*/
func DrawGridColumn(grid *FCView, column *FCGridColumn, paint *FCPaint, left float64, top float64, right float64, bottom float64) {
    inGrid := grid.GetGrid()    
    tSize := paint.TextSize(column.Text, column.Font)
    if column.BackColor != "none" {
        paint.FillRect(column.BackColor, left, top, right, bottom)
    }
    if column.BorderColor != "none" {
        paint.DrawRect(column.BorderColor, 1, 0, left, top, right, bottom)
    }
    paint.DrawText(column.Text, column.TextColor, column.Font, left + (column.Width - tSize.Cx) / 2, top + (inGrid.HeaderHeight - tSize.Cy) / 2)
    if column.Sort == "asc" {
        cR := (bottom - top) / 4
        oX := right - cR * 2
        oY := top + (bottom - top) / 2
        var drawPoints []FCPoint
		drawPoints = append(drawPoints, CreatePoint(oX, oY - cR))
		drawPoints = append(drawPoints, CreatePoint(oX - cR, oY + cR))
		drawPoints = append(drawPoints, CreatePoint(oX + cR, oY + cR))
		paint.FillPolygon(column.TextColor, drawPoints)
    }else if column.Sort == "desc" {
        cR := (bottom - top) / 4
        oX := right - cR * 2
        oY := top + (bottom - top) / 2
        var drawPoints []FCPoint
		drawPoints = append(drawPoints, CreatePoint(oX, oY + cR))
		drawPoints = append(drawPoints, CreatePoint(oX - cR, oY - cR))
		drawPoints = append(drawPoints, CreatePoint(oX + cR, oY - cR))
        paint.FillPolygon(column.TextColor, drawPoints)
    }
}

/*
* 绘制表格
* grid:表格
* paint:绘图对象
* clipRect:裁剪区域
*/
func DrawGrid(grid *FCView, paint *FCPaint, clipRect FCRect) {
    inGrid := grid.GetGrid()    
    cTop := -grid.ScrollV + inGrid.HeaderHeight
    //绘制行
    colLeft := 0.0
    if len(grid.Views) > 0{
        for i := 0; i < len(grid.Views); i++ {
            grid.Views[i].Visible = false
        }
    }
    if len(inGrid.Columns) > 0{
        for i := 0; i < len(inGrid.Columns); i++ {
            if(len(inGrid.Columns[i].WidthStr) > 0){
                newWidthStr := strings.Replace(inGrid.Columns[i].WidthStr, "(", "", -1)
                inGrid.Columns[i].Width = ConvertToFloat64(newWidthStr) * grid.Size.Cx / 100
            }
            colRect := CreateRect(colLeft, 0, colLeft + inGrid.Columns[i].Width, inGrid.HeaderHeight)
            inGrid.Columns[i].Bounds = colRect
            inGrid.Columns[i].Index = i
            colLeft += inGrid.Columns[i].Width
        }
    }
    if len(inGrid.Rows) > 0{
        for i := 0; i < len(inGrid.Rows); i++ {
            row := inGrid.Rows[i]
            row.Index = i
            if row.Visible {
                rTop := cTop
                rBottom := cTop + inGrid.RowHeight
                if rBottom >= 0 && cTop <= grid.Size.Cy {
                    for j := 0; j < len(row.Cells); j++ {
                        cell := row.Cells[j]
                        gridColumn := cell.GetColumn()
                        if !gridColumn.IsNotEmpty {
                            gridColumn = inGrid.Columns[j]
                        }
                        if gridColumn.Visible {
                            if !gridColumn.Frozen {
                                cellWidth := gridColumn.Width
                                colSpan := cell.ColSpan
                                if colSpan > 1 {
                                    for n := 1; n < colSpan; n++ {
                                        spanColumn := inGrid.Columns[gridColumn.Index + n]
                                        if spanColumn.IsNotEmpty && spanColumn.Visible {
                                            cellWidth += spanColumn.Width
                                        }
                                    }
                                }
                                cellHeight := inGrid.RowHeight
                                rowSpan := cell.RowSpan
                                if rowSpan > 1 {
                                    for n := 1; n < rowSpan; n++ {
                                        spanRow := inGrid.Rows[i + n]
                                        if spanRow.IsNotEmpty && spanRow.Visible {
                                            cellHeight += inGrid.RowHeight
                                        }
                                    }
                                }
                                cRect := CreateRect(gridColumn.Bounds.Left - grid.ScrollH, rTop, gridColumn.Bounds.Left + cellWidth - grid.ScrollH, rTop + cellHeight)
                                if cRect.Right >= 0 && cRect.Left < grid.Size.Cx {
                                    if inGrid.OnPaintGridCell != nil{
                                        inGrid.OnPaintGridCell(grid, row, gridColumn, cell, paint, cRect.Left, cRect.Top, cRect.Right, cRect.Bottom)
                                    }else if paint.OnPaintGridCell != nil{
                                        paint.OnPaintGridCell(grid, row, gridColumn, cell, paint, cRect.Left, cRect.Top, cRect.Right, cRect.Bottom)
                                    }else{
                                        DrawGridCell(grid, row, gridColumn, cell, paint, cRect.Left, cRect.Top, cRect.Right, cRect.Bottom)
                                    }
                                    if len(cell.View) > 0{
                                        cellView := cell.GetView()
                                        cellView.Visible = true
                                        cellView.Location = CreatePoint(cRect.Left + grid.ScrollH, cRect.Top + grid.ScrollV)
                                        cellView.Size = CreateSize(cRect.Right - cRect.Left, cRect.Bottom - cRect.Top)
                                    }
                                }
                            }
                        }
                    }
                }
                if rBottom >= 0 && cTop <= grid.Size.Cy {
                    for j := 0; j < len(row.Cells); j++ {
                        cell := row.Cells[j]
                        gridColumn := cell.GetColumn()
                        if !gridColumn.IsNotEmpty {
                            gridColumn = inGrid.Columns[j]
                        }
                        if gridColumn.Visible {
                            if gridColumn.Frozen{
                                cellWidth := gridColumn.Width
                                colSpan := cell.ColSpan
                                if colSpan > 1 {
                                    for n := 1; n < colSpan; n++ {
                                        spanColumn := inGrid.Columns[gridColumn.Index + n]
                                        if spanColumn.IsNotEmpty && spanColumn.Visible {
                                            cellWidth += spanColumn.Width
                                        }
                                    }
                                }
                                cellHeight := inGrid.RowHeight
                                rowSpan := cell.RowSpan
                                if rowSpan > 1 {
                                    for n := 1; n < rowSpan; n++ {
                                        spanRow := inGrid.Rows[i + n]
                                        if spanRow.IsNotEmpty && spanRow.Visible {
                                            cellHeight += inGrid.RowHeight
                                        }
                                    }
                                }
                                cRect := CreateRect(gridColumn.Bounds.Left - grid.ScrollH, rTop, gridColumn.Bounds.Left + cellWidth - grid.ScrollH, rTop + cellHeight)
                                if cRect.Right >= 0 && cRect.Left < grid.Size.Cx {
                                    if inGrid.OnPaintGridCell != nil{
                                        inGrid.OnPaintGridCell(grid, row, gridColumn, cell, paint, cRect.Left, cRect.Top, cRect.Right, cRect.Bottom)
                                    }else if paint.OnPaintGridCell != nil{
                                        paint.OnPaintGridCell(grid, row, gridColumn, cell, paint, cRect.Left, cRect.Top, cRect.Right, cRect.Bottom)
                                    }else{
                                        DrawGridCell(grid, row, gridColumn, cell, paint, cRect.Left, cRect.Top, cRect.Right, cRect.Bottom)
                                    }
                                    if len(cell.View) > 0{
                                        cellView := cell.GetView()
                                        cellView.Visible = true
                                        cellView.Location = CreatePoint(cRect.Left + grid.ScrollH, cRect.Top + grid.ScrollV)
                                        cellView.Size = CreateSize(cRect.Right - cRect.Left, cRect.Bottom - cRect.Top)
                                    }
                                }
                            }
                        }
                    }
                }
                if cTop > grid.Size.Cy {
                    break
                }
                cTop += inGrid.RowHeight
            }
        }
    }
}

/*
* 绘制表格的滚动条
* grid:表格
* paint:绘图对象
* clipRect:裁剪区域
*/
func DrawGridScrollBar(grid *FCView, paint *FCPaint, clipRect FCRect) {
    grid.HScrollIsVisible = false
    grid.VScrollIsVisible = false
    inGrid := grid.GetGrid() 
    if inGrid.HeaderHeight > 0 && len(inGrid.Columns) > 0 {
        cLeft := -grid.ScrollH
        //绘制列
        for i := 0; i < len(inGrid.Columns); i++ {
            gridColumn := inGrid.Columns[i]
            if inGrid.Columns[i].Visible {
                if !gridColumn.Frozen {
                    if inGrid.OnPaintGridColumn != nil{
                        inGrid.OnPaintGridColumn(grid, inGrid.Columns[i], paint, cLeft, 0, cLeft + gridColumn.Width, inGrid.HeaderHeight)
                    }else if paint.OnPaintGridColumn != nil{
                        paint.OnPaintGridColumn(grid, inGrid.Columns[i], paint, cLeft, 0, cLeft + gridColumn.Width, inGrid.HeaderHeight)
                    }else{
                        DrawGridColumn(grid, inGrid.Columns[i], paint, cLeft, 0, cLeft + gridColumn.Width, inGrid.HeaderHeight)
                    }
                }
                cLeft += gridColumn.Width
            }
        }
        cLeft = 0
        for i := 0; i < len(inGrid.Columns); i++ {
            gridColumn := inGrid.Columns[i]
            if inGrid.Columns[i].Visible {
                if gridColumn.Frozen {
                    if inGrid.OnPaintGridColumn != nil{
                        inGrid.OnPaintGridColumn(grid, inGrid.Columns[i], paint, cLeft, 0, cLeft + gridColumn.Width, inGrid.HeaderHeight)
                    }else if paint.OnPaintGridColumn != nil{
                        paint.OnPaintGridColumn(grid, inGrid.Columns[i], paint, cLeft, 0, cLeft + gridColumn.Width, inGrid.HeaderHeight)
                    }else{
                        DrawGridColumn(grid, inGrid.Columns[i], paint, cLeft, 0, cLeft + gridColumn.Width, inGrid.HeaderHeight)
                    }
                }
                cLeft += gridColumn.Width
            }
        }
    }
    if grid.ShowHScrollBar {
        contentWidth := GetGridContentWidth(grid)
        if contentWidth > 0 && contentWidth > grid.Size.Cx {
            sLeft := grid.ScrollH / contentWidth * grid.Size.Cx
            sRight := (grid.ScrollH + grid.Size.Cx) / contentWidth * grid.Size.Cx
            if sRight - sLeft < grid.ScrollSize {
                sRight = sLeft + grid.ScrollSize
            }
            if paint.GetTouchMoveView() == grid && (grid.HoverScrollHButton || grid.DownScrollHButton){
                paint.FillRect(grid.ScrollBarHoveredColor, sLeft, grid.Size.Cy - grid.ScrollSize, sRight, grid.Size.Cy)
            } else {
                paint.FillRect(grid.ScrollBarColor, sLeft, grid.Size.Cy - grid.ScrollSize, sRight, grid.Size.Cy)
            }
            grid.HScrollIsVisible = true
        }
    }
    if grid.ShowVScrollBar {
        contentHeight := GetGridContentHeight(grid)
        if contentHeight > 0 && contentHeight > grid.Size.Cy - inGrid.HeaderHeight {
            sTop := inGrid.HeaderHeight + grid.ScrollV / contentHeight * (grid.Size.Cy - inGrid.HeaderHeight - grid.ScrollSize)
            sBottom := sTop + ((grid.Size.Cy - inGrid.HeaderHeight - grid.ScrollSize)) / contentHeight * (grid.Size.Cy - inGrid.HeaderHeight - grid.ScrollSize)
            if sBottom - sTop < grid.ScrollSize {
                sBottom = sTop + grid.ScrollSize
            }
            if paint.GetTouchMoveView() == grid && (grid.HoverScrollVButton || grid.DownScrollVButton) {
                paint.FillRect(grid.ScrollBarHoveredColor, grid.Size.Cx - grid.ScrollSize, sTop, grid.Size.Cx, sBottom)
            } else {
                paint.FillRect(grid.ScrollBarColor, grid.Size.Cx - grid.ScrollSize, sTop, grid.Size.Cx, sBottom)
            }
            grid.VScrollIsVisible = true
        }
    }
}

/*
* 获取内容的宽度
* grid:表格
*/
func GetGridContentWidth(grid *FCView)(float64) {
    inGrid := grid.GetGrid()    
    cWidth := 0.0
    if len(inGrid.Columns) > 0{
        for i := 0; i < len(inGrid.Columns); i++ {
            if inGrid.Columns[i].Visible {
                cWidth += inGrid.Columns[i].Width
            }
        }
    }
    return cWidth
}

/*
* 获取内容的高度
* grid:表格
*/
func GetGridContentHeight(grid *FCView)(float64) {
    inGrid := grid.GetGrid()    
    cHeight := 0.0
    if len(inGrid.Rows) > 0{
        for i := 0; i < len(inGrid.Rows); i++ {
            if inGrid.Rows[i].Visible {
                cHeight += inGrid.RowHeight
            }
        }
    }
    return cHeight
}

/*
* 表格的鼠标移动方法
* grid: 表格
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
*/
func TouchMoveGrid(grid *FCView, firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint) {
    inGrid := grid.GetGrid()        
    grid.HoverScrollHButton = false
    grid.HoverScrollVButton = false
    mp := CreatePoint(firstPoint.X, firstPoint.Y)
    paint := grid.GetPaint()
    if firstTouch {
        if paint.ResizeColumnState != 0 {
            gridColumn := inGrid.Columns[paint.ResizeColumnIndex]
            newWidth := paint.ResizeColumnBeginWidth + (mp.X - grid.StartPoint.X)
            if newWidth > 10 {
                gridColumn.Width = newWidth
            }
            return
        }
        if grid.ShowHScrollBar || grid.ShowVScrollBar {
            if grid.DownScrollHButton {
                contentWidth := GetGridContentWidth(grid)
                subX := (mp.X - grid.StartPoint.X) / grid.Size.Cx * contentWidth
                newScrollH := grid.StartScrollH + subX
                if newScrollH < 0 {
                    newScrollH = 0
                } else if newScrollH > contentWidth - grid.Size.Cx {
                    newScrollH = contentWidth - grid.Size.Cx
                }
                grid.ScrollH = newScrollH
                paint.CancelClick = true
                return
            } else if grid.DownScrollVButton {
                contentHeight := GetGridContentHeight(grid)
                subY := (mp.Y - grid.StartPoint.Y) / (grid.Size.Cy - inGrid.HeaderHeight - grid.ScrollSize) * contentHeight
                newScrollV := grid.StartScrollV + subY
                if newScrollV < 0 {
                    newScrollV = 0
                } else if newScrollV > contentHeight - (grid.Size.Cy - inGrid.HeaderHeight - grid.ScrollSize) {
                    newScrollV = contentHeight - (grid.Size.Cy - inGrid.HeaderHeight - grid.ScrollSize)
                }
                grid.ScrollV = newScrollV
                paint.CancelClick = true
                return
            }
        }
        if grid.AllowDragScroll {
            contentWidth := GetGridContentWidth(grid)
            if contentWidth > grid.Size.Cx - grid.ScrollSize {
                subX := grid.StartPoint.X - mp.X
                newScrollH := grid.StartScrollH + subX
                if newScrollH < 0 {
                    newScrollH = 0
                } else if newScrollH > contentWidth - grid.Size.Cx{
                    newScrollH = contentWidth - grid.Size.Cx
                }
                grid.ScrollH = newScrollH
                if subX > 5 || subX < -5 {
                    paint.CancelClick = true
                }
            }
            contentHeight := GetGridContentHeight(grid)
            if contentHeight > grid.Size.Cy - inGrid.HeaderHeight - grid.ScrollSize {
                subY := grid.StartPoint.Y - mp.Y
                newScrollV := grid.StartScrollV + subY
                if newScrollV < 0{
                    newScrollV = 0
                } else if newScrollV > contentHeight - (grid.Size.Cy - inGrid.HeaderHeight - grid.ScrollSize) {
                    newScrollV = contentHeight - (grid.Size.Cy - inGrid.HeaderHeight - grid.ScrollSize)
                }
                grid.ScrollV = newScrollV
                if subY > 5 || subY < -5 {
                    paint.CancelClick = true
                }
            }
        }
    } else {
        if grid.ShowHScrollBar {
            contentWidth := GetGridContentWidth(grid)
            if contentWidth > 0 && contentWidth > grid.Size.Cx - grid.ScrollSize {
                sLeft := grid.ScrollH / contentWidth * grid.Size.Cx
                sRight := (grid.ScrollH + grid.Size.Cx) / contentWidth * grid.Size.Cx
                if sRight - sLeft < grid.ScrollSize {
                    sRight = sLeft + grid.ScrollSize
                }
                if mp.X >= sLeft && mp.X <= sRight && mp.Y >= grid.Size.Cy - grid.ScrollSize && mp.Y <= grid.Size.Cy {
                    grid.HoverScrollHButton = true
                    return
                } else {
                    grid.HoverScrollHButton = false
                }
            }
        }
        if grid.ShowVScrollBar {
            contentHeight := GetGridContentHeight(grid)
            if contentHeight > 0 && contentHeight > grid.Size.Cy - inGrid.HeaderHeight - grid.ScrollSize {
                sTop := inGrid.HeaderHeight + grid.ScrollV / contentHeight * (grid.Size.Cy - inGrid.HeaderHeight - grid.ScrollSize)
                sBottom := inGrid.HeaderHeight + (grid.ScrollV + (grid.Size.Cy - inGrid.HeaderHeight - grid.ScrollSize)) / contentHeight * (grid.Size.Cy - inGrid.HeaderHeight - grid.ScrollSize)
                if sBottom - sTop < grid.ScrollSize {
                    sBottom = sTop + grid.ScrollSize
                }
                if mp.X >= grid.Size.Cx - grid.ScrollSize && mp.X <= grid.Size.Cx && mp.Y >= sTop && mp.Y <= sBottom {
                    grid.HoverScrollVButton = true
                    return
                } else {
                    grid.HoverScrollVButton = false
                }
            }
        }
    }
}


/*
* 表格的鼠标按下方法
* grid: 表格
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
* clicks:点击次数
*/
func TouchDownGrid(grid *FCView, firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint, clicks int) {
    inGrid := grid.GetGrid()        
    mp := CreatePoint(firstPoint.X, firstPoint.Y)
    grid.StartPoint = mp
    grid.DownScrollHButton = false
    grid.DownScrollVButton = false
    grid.HoverScrollHButton = false
    grid.HoverScrollVButton = false
    if grid.ShowHScrollBar{
        contentWidth := GetGridContentWidth(grid)
        if contentWidth > 0 && contentWidth > grid.Size.Cx - grid.ScrollSize{
            sLeft := grid.ScrollH / contentWidth * grid.Size.Cx
            sRight := (grid.ScrollH + grid.Size.Cx) / contentWidth * grid.Size.Cx
            if sRight - sLeft < grid.ScrollSize {
                sRight = sLeft + grid.ScrollSize
            }
            if mp.X >= sLeft && mp.X <= sRight && mp.Y >= grid.Size.Cy - grid.ScrollSize && mp.Y <= grid.Size.Cy{
                grid.DownScrollHButton = true
                grid.StartScrollH = grid.ScrollH
                return
            }
        }
    }
    if grid.ShowVScrollBar {
        contentHeight := GetGridContentHeight(grid)
        if contentHeight > 0 && contentHeight > grid.Size.Cy - inGrid.HeaderHeight - grid.ScrollSize {
            sTop := inGrid.HeaderHeight + grid.ScrollV / contentHeight * (grid.Size.Cy - inGrid.HeaderHeight - grid.ScrollSize)
            sBottom := inGrid.HeaderHeight + (grid.ScrollV + (grid.Size.Cy - inGrid.HeaderHeight - grid.ScrollSize)) / contentHeight * (grid.Size.Cy - inGrid.HeaderHeight - grid.ScrollSize)
            if sBottom - sTop < grid.ScrollSize {
                sBottom = sTop + grid.ScrollSize
            }
            if mp.X >= grid.Size.Cx - grid.ScrollSize && mp.X <= grid.Size.Cx && mp.Y >= sTop && mp.Y <= sBottom {
                grid.DownScrollVButton = true
                grid.StartScrollV = grid.ScrollV
                return
            }
        }
    }
    if grid.AllowDragScroll {
        grid.StartScrollH = grid.ScrollH
        grid.StartScrollV = grid.ScrollV
    }
    colLeft := 0.0
    if len(inGrid.Columns) > 0{
        for i := 0; i < len(inGrid.Columns); i++ {
            colRect := CreateRect(colLeft, 0, colLeft + inGrid.Columns[i].Width, inGrid.HeaderHeight)
            inGrid.Columns[i].Bounds = colRect
            inGrid.Columns[i].Index = i
            colLeft += inGrid.Columns[i].Width
        }
    }
    paint := grid.GetPaint()
    paint.ResizeColumnState = 0
    paint.ResizeColumnBeginWidth = 0
    if (inGrid.HeaderHeight > 0 && mp.Y <= inGrid.HeaderHeight && len(inGrid.Columns) > 0) {
        //绘制列
        for i := 0; i < len(inGrid.Columns); i++ {
            gridColumn := inGrid.Columns[i]
            if gridColumn.Visible {
                bounds := gridColumn.Bounds
                if mp.X >= bounds.Left - grid.ScrollH && mp.X <= bounds.Right - grid.ScrollH {
                    if gridColumn.Index > 0 && mp.X < bounds.Left + 5 - grid.ScrollH {
                        paint.ResizeColumnState = 1
                        paint.ResizeColumnBeginWidth = inGrid.Columns[gridColumn.Index - 1].Bounds.Right - inGrid.Columns[gridColumn.Index - 1].Bounds.Left
                        paint.ResizeColumnIndex = gridColumn.Index - 1
                        return
                    }else if mp.X > bounds.Right - 5 - grid.ScrollH{
                        paint.ResizeColumnState = 2
                        paint.ResizeColumnBeginWidth = bounds.Right - bounds.Left
                        paint.ResizeColumnIndex = gridColumn.Index
                        return
                    }
                    break
                }
            }
        }
    }
}

type SortGridRowAsc []*FCGridRow
func (a SortGridRowAsc) Len() int  { return len(a) }
func (a SortGridRowAsc) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a SortGridRowAsc) Less(i, j int) bool{
    leftCell := a[i].Cells[a[i].SortColIndex]
    rightCell :=  a[j].Cells[a[j].SortColIndex]
    leftColumn := leftCell.GetColumn()
    if(leftColumn.ColType == "double"){
        leftValue := ConvertToFloat64(leftCell.Value)
        rightValue := ConvertToFloat64(rightCell.Value)
        if(rightValue > leftValue){
            return true;
        }else{
            return false;
        }
    }else if(leftColumn.ColType == "int"){
        leftValue := ConvertToInt(leftCell.Value)
        rightValue := ConvertToInt(rightCell.Value)
        if(rightValue > leftValue){
            return true;
        }else{
            return false;
        }
    }else if(leftColumn.ColType == "bool"){
        leftValue := 1
        rightValue := 1
        if(leftCell.Value == "false"){
            leftValue = 0
        }
        if(rightCell.Value == "false"){
            rightValue =  0
        }
        if(rightValue > leftValue){
            return true;
        }else{
            return false;
        }
    }else{
        return rightCell.Value > leftCell.Value
    }
}

type SortGridRowDesc []*FCGridRow
func (a SortGridRowDesc) Len() int  { return len(a) }
func (a SortGridRowDesc) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
func (a SortGridRowDesc) Less(i, j int) bool{
    leftCell := a[i].Cells[a[i].SortColIndex]
    rightCell :=  a[j].Cells[a[j].SortColIndex]
     leftColumn := leftCell.GetColumn()
    if(leftColumn.ColType == "double"){
        leftValue := ConvertToFloat64(leftCell.Value)
        rightValue := ConvertToFloat64(rightCell.Value)
        if(rightValue < leftValue){
            return true;
        }else{
            return false;
        }
    }else if(leftColumn.ColType == "int"){
        leftValue := ConvertToInt(leftCell.Value)
        rightValue := ConvertToInt(rightCell.Value)
        if(rightValue < leftValue){
            return true;
        }else{
            return false;
        }
    }else if(leftColumn.ColType == "bool"){
        leftValue := 1
        rightValue := 1
        if(leftCell.Value == "false"){
            leftValue = 0
        }
        if(rightCell.Value == "false"){
            rightValue =  0
        }
        if(rightValue < leftValue){
            return true;
        }else{
            return false;
        }
    }else{
        return rightCell.Value < leftCell.Value
    }
}

/*
* 表格的鼠标抬起方法
* grid: 表格
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
* clicks:点击次数
*/
func TouchUpGrid(grid *FCView, firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint, clicks int) {
    grid.HoverScrollHButton = false
    grid.HoverScrollVButton = false
    grid.DownScrollHButton = false
    grid.DownScrollVButton = false
    if grid.GetPaint().CancelClick{
        return
    }
    inGrid := grid.GetGrid()        
    cTop := -grid.ScrollV + inGrid.HeaderHeight
    //绘制行
    colLeft := 0.0
    if len(inGrid.Columns) > 0{
        for i := 0; i < len(inGrid.Columns); i++ {
            colRect := CreateRect(colLeft, 0, colLeft + inGrid.Columns[i].Width, inGrid.HeaderHeight)
            inGrid.Columns[i].Bounds = colRect
            inGrid.Columns[i].Index = i
            colLeft += inGrid.Columns[i].Width
        }
    }
    //判断列头
	if inGrid.HeaderHeight > 0 && firstPoint.Y <= inGrid.HeaderHeight{
        cLeft := 0.0
		for i := 0; i < len(inGrid.Columns); i++ {
            gridColumn := inGrid.Columns[i]
			if gridColumn.Visible{
				if gridColumn.Frozen{
					if firstPoint.X >= cLeft && firstPoint.X <= cLeft + gridColumn.Width{
                        for j := 0; j < len(inGrid.Columns); j++{
							tColumn := inGrid.Columns[j]
							if tColumn == gridColumn {
								if tColumn.AllowSort {
									if (tColumn.Sort == "none" || tColumn.Sort == "desc") {
										tColumn.Sort = "asc"
                                        for r := 0; r < len(inGrid.Rows); r++{
                                            inGrid.Rows[r].SortColIndex = j
                                        }
                                        sort.Sort(SortGridRowAsc(inGrid.Rows))
									} else {
										tColumn.Sort = "desc"
                                        for r := 0; r < len(inGrid.Rows); r++{
                                            inGrid.Rows[r].SortColIndex = j
                                        }
                                        sort.Sort(SortGridRowDesc(inGrid.Rows))
									}
								} else {
									tColumn.Sort = "none"
								}
							} else {
								tColumn.Sort = "none"
							}
						}
						if inGrid.OnClickGridColumn != nil{
                            inGrid.OnClickGridColumn(grid, gridColumn, firstTouch, firstPoint, secondTouch, secondPoint, clicks)
                        }else if grid.GetPaint().OnClickGridColumn != nil{
							grid.GetPaint().OnClickGridColumn(grid, gridColumn, firstTouch, firstPoint, secondTouch, secondPoint, clicks)
                        }
						return
                    }
                }
				cLeft += gridColumn.Width
            }
        }
		cLeft = -grid.ScrollH
        for i := 0; i < len(inGrid.Columns); i++ {
            gridColumn := inGrid.Columns[i]
			if gridColumn.Visible{
				if !gridColumn.Frozen{
					if firstPoint.X >= cLeft && firstPoint.X <= cLeft + gridColumn.Width{
                        for j := 0; j < len(inGrid.Columns); j++{
							tColumn := inGrid.Columns[j]
							if tColumn == gridColumn {
								if tColumn.AllowSort {
									if (tColumn.Sort == "none" || tColumn.Sort == "desc") {
										tColumn.Sort = "asc"
                                        for r := 0; r < len(inGrid.Rows); r++{
                                            inGrid.Rows[r].SortColIndex = j
                                        }
                                        sort.Sort(SortGridRowAsc(inGrid.Rows))
									} else {
										tColumn.Sort = "desc"
                                        for r := 0; r < len(inGrid.Rows); r++{
                                            inGrid.Rows[r].SortColIndex = j
                                        }
                                        sort.Sort(SortGridRowDesc(inGrid.Rows))
									}
								} else {
									tColumn.Sort = "none"
								}
							} else {
								tColumn.Sort = "none"
							}
						}
						if inGrid.OnClickGridColumn != nil{
                            inGrid.OnClickGridColumn(grid, gridColumn, firstTouch, firstPoint, secondTouch, secondPoint, clicks)
                        }else if grid.GetPaint().OnClickGridColumn != nil{
							grid.GetPaint().OnClickGridColumn(grid, gridColumn, firstTouch, firstPoint, secondTouch, secondPoint, clicks)
                        }
						return
                    }
                }
				cLeft += gridColumn.Width
            }
        }
    }
    if len(inGrid.Rows) > 0{
        for i := 0; i < len(inGrid.Rows); i++ {
            row := inGrid.Rows[i]
            if row.Visible {
                rTop := cTop
                rBottom := cTop + inGrid.RowHeight
                if rBottom >= 0 && cTop <= grid.Size.Cy {
                    for j := 0; j < len(row.Cells); j++ {
                        cell := row.Cells[j]
                        gridColumn := cell.GetColumn()
                        if !gridColumn.IsNotEmpty {
                            gridColumn = inGrid.Columns[j]
                        }
                        if gridColumn.Visible {
                            if gridColumn.Frozen {
                                cellWidth := gridColumn.Width
                                colSpan := cell.ColSpan
                                if colSpan > 1 {
                                    for n := 1; n < colSpan; n++ {
                                        spanColumn := inGrid.Columns[gridColumn.Index + n]
                                        if spanColumn.IsNotEmpty && spanColumn.Visible{
                                            cellWidth += spanColumn.Width
                                        }
                                    }
                                }
                                cellHeight := inGrid.RowHeight
                                rowSpan := cell.RowSpan
                                if rowSpan > 1 {
                                    for n := 1; 1 < rowSpan; n++ {
                                        spanRow := inGrid.Rows[i + n]
                                        if spanRow.IsNotEmpty && spanRow.Visible {
                                            cellHeight += inGrid.RowHeight
                                        }
                                    }
                                }

                                cRect := CreateRect(gridColumn.Bounds.Left, rTop, gridColumn.Bounds.Left + cellWidth, rTop + cellHeight)
                                if cRect.Right >= 0 && cRect.Left < grid.Size.Cx {
                                    if firstPoint.X >= cRect.Left && firstPoint.X <= cRect.Right && firstPoint.Y >= cRect.Top && firstPoint.Y <= cRect.Bottom {
                                        for r := 0; r < len(inGrid.Rows); r++ {
                                            subRow := inGrid.Rows[r]
                                            if subRow == row {
                                                subRow.Selected = true
                                            } else {
                                                subRow.Selected = false
                                            }
                                        }
                                        if inGrid.OnClickGridCell != nil{
                                            inGrid.OnClickGridCell(grid, row, gridColumn, cell, firstTouch, firstPoint, secondTouch, secondPoint, clicks)
                                        }else if grid.GetPaint().OnClickGridCell != nil{
                                            grid.GetPaint().OnClickGridCell(grid, row, gridColumn, cell, firstTouch, firstPoint, secondTouch, secondPoint, clicks)
                                        }
                                        return
                                    }
                                }
                            }
                        }
                    }
                }
                if rBottom >= 0 && cTop <= grid.Size.Cy {
                     for j := 0; j < len(row.Cells); j++ {
                        cell := row.Cells[j]
                        gridColumn := cell.GetColumn()
                        if !gridColumn.IsNotEmpty {
                            gridColumn = inGrid.Columns[j]
                        }
                        if gridColumn.Visible {
                            if !gridColumn.Frozen {
                                cellWidth := gridColumn.Width
                                colSpan := cell.ColSpan
                                if colSpan > 1 {
                                    for n := 1; n < colSpan; n++ {
                                        spanColumn := inGrid.Columns[gridColumn.Index + n]
                                        if spanColumn.IsNotEmpty && spanColumn.Visible{
                                            cellWidth += spanColumn.Width
                                        }
                                    }
                                }
                                cellHeight := inGrid.RowHeight
                                rowSpan := cell.RowSpan
                                if rowSpan > 1 {
                                    for n := 1; 1 < rowSpan; n++ {
                                        spanRow := inGrid.Rows[i + n]
                                        if spanRow.IsNotEmpty && spanRow.Visible {
                                            cellHeight += inGrid.RowHeight
                                        }
                                    }
                                }

                                cRect := CreateRect(gridColumn.Bounds.Left - grid.ScrollH, rTop, gridColumn.Bounds.Left + cellWidth - grid.ScrollH, rTop + cellHeight)
                                if cRect.Right >= 0 && cRect.Left < grid.Size.Cx {
                                    if firstPoint.X >= cRect.Left && firstPoint.X <= cRect.Right && firstPoint.Y >= cRect.Top && firstPoint.Y <= cRect.Bottom {
                                        for r := 0; r < len(inGrid.Rows); r++ {
                                            subRow := inGrid.Rows[r]
                                            if subRow == row {
                                                subRow.Selected = true
                                            } else {
                                                subRow.Selected = false
                                            }
                                        }
                                        if inGrid.OnClickGridCell != nil{
                                            inGrid.OnClickGridCell(grid, row, gridColumn, cell, firstTouch, firstPoint, secondTouch, secondPoint, clicks)
                                        }else if grid.GetPaint().OnClickGridCell != nil{
                                            grid.GetPaint().OnClickGridCell(grid, row, gridColumn, cell, firstTouch, firstPoint, secondTouch, secondPoint, clicks)
                                        }
                                        return
                                    }
                                }
                            }
                        }
                    }
                }
                if cTop > grid.Size.Cy {
                    break
                }
                cTop += inGrid.RowHeight
            }
        }
    }
}

/*
* 表格的鼠标滚轮方法
* grid:表格
* delta:滚轮值
*/
func TouchWheelGrid(grid *FCView, delta int) {
    inGrid := grid.GetGrid()        
    oldScrollV := grid.ScrollV
    if delta < 0 {
        oldScrollV -= 20
    } else if delta > 0 {
        oldScrollV += 20
    }
    contentHeight := GetGridContentHeight(grid)
    if contentHeight < grid.Size.Cy - inGrid.HeaderHeight - grid.ScrollSize {
        grid.ScrollV = 0
    } else {
        if oldScrollV < 0 {
            oldScrollV = 0
        } else if oldScrollV > contentHeight - grid.Size.Cy + inGrid.HeaderHeight + grid.ScrollSize{
            oldScrollV = contentHeight - grid.Size.Cy + inGrid.HeaderHeight + grid.ScrollSize
        }
        grid.ScrollV = oldScrollV
    }
}

/*
* 创建文本框实体
* textBox:文本框
*/
func CreateInputTextBox(textBox *FCView){
    var document js.Value = js.
        Global().
        Get("document")
    var input js.Value = document.Call("createElement", "input")
    textBox.Input = input
    textBox.HasInput = true
    input.Set("type", "text")
    input.Get("style").Set("position", "absolute")
    input.Get("style").Set("display", "none")
    input.Get("style").Set("box-sizing", "border-box")
    paint := textBox.GetPaint()
    if len(textBox.Font) > 0{
        strs := strings.Split(textBox.Font, ",")
        fontFamily := strs[0]
	    if fontFamily == "Default" {
		    fontFamily = paint.SystemFont
        }
	    sFont := ConvertFloat64ToStr(math.Floor(ConvertToFloat64(strs[1]))) + "px " + fontFamily;
        if paint.ScaleFactorX != 1 || paint.ScaleFactorY != 1 {
            newSize := math.Min(paint.ScaleFactorX, paint.ScaleFactorY) * ConvertToFloat64(strs[1])
            sFont = ConvertFloat64ToStr(math.Floor(newSize)) + "px " + fontFamily;
	    }
        for i := 2; i < len(strs); i++ {
		    iStr := strings.ToLower(strs[i]);
		    if (iStr == "bold" || iStr == "italic") {
			    sFont = iStr + " " + sFont;
		    }
	    }
        input.Get("style").Set("font", sFont)
    }
    document.Get("body").Call("appendChild", input)
    input.Set("text", textBox.Text)
}

/*
* 重置布局图层
* layout:布局层
*/
func ResetLayoutDiv(layout *FCView) {
    inLayout := layout.GetLayoutDiv()
    padding := CreatePadding(0, 0, 0, 0)
    if layout.Padding.IsNotEmpty{
        padding = layout.Padding
    }
    vPos := 0
    left := padding.Left
    top := padding.Top
    width := layout.Size.Cx - padding.Left - padding.Right
    height := layout.Size.Cy - padding.Top - padding.Bottom
    if len(layout.Views) > 0{
        for i := 0; i < len(layout.Views); i++ {
            view := layout.Views[i]
            if view.Visible {
                size := view.Size
                margin := CreatePadding(0, 0, 0, 0)
                if view.Margin.IsNotEmpty{
                    margin = view.Margin
                }
                cLeft := view.Location.X
                cTop := view.Location.Y
                cWidth := size.Cx
                cHeight := size.Cy
                nLeft := cLeft
                nTop := cTop
                nWidth := cWidth
                nHeight := cHeight
                if inLayout.LayoutStyle == "bottomtotop" {
                    if i == 0{
                        top = height - padding.Top
                    }
                    lWidth := 0.0
                    if inLayout.AutoWrap {
                        lWidth = size.Cx
                        lTop := top - margin.Top - cHeight - margin.Bottom
                        if lTop < padding.Top {
                            if (vPos != 0) {
                                left += cWidth + margin.Left
                            }
                            top = height - padding.Top
                        }
                    }else {
                        lWidth = width - margin.Left - margin.Right
                    }
                    top -= cHeight + margin.Bottom
                    nLeft = left + margin.Left
                    nWidth = lWidth
                    nTop = top
                } else if inLayout.LayoutStyle == "lefttoright" {
                    lHeight := 0.0
                    if inLayout.AutoWrap {
                        lHeight = size.Cy
                        lRight := left + margin.Left + cWidth + margin.Right
                        if lRight > width {
                            left = padding.Left
                            if vPos != 0 {
                                top += cHeight + margin.Top
                            }
                        }
                    }else {
                        lHeight = height - margin.Top - margin.Bottom
                    }
                    left += margin.Left
                    nLeft = left
                    nTop = top + margin.Top
                    nHeight = lHeight
                    left += cWidth + margin.Right
                } else if inLayout.LayoutStyle == "righttoleft" {
                    if i == 0 {
                        left = width - padding.Left
                    }
                    lHeight := 0.0
                    if inLayout.AutoWrap {
                        lHeight = size.Cy
                        lLeft := left - margin.Left - cWidth - margin.Right
                        if lLeft < padding.Left {
                            left = width - padding.Left
                            if vPos != 0 {
                                top += cHeight + margin.Top
                            }
                        }
                    }else {
                        lHeight = height - margin.Top - margin.Bottom
                    }
                    left -= cWidth + margin.Left
                    nLeft = left
                    nTop = top + margin.Top
                    nHeight = lHeight
                } else if inLayout.LayoutStyle == "toptobottom" {
                    lWidth := 0.0
                    if inLayout.AutoWrap {
                        lWidth = size.Cx
                        lBottom := top + margin.Top + cHeight + margin.Bottom
                        if lBottom > height{
                            if vPos != 0 {
                                left += cWidth + margin.Left + margin.Right
                            }
                            top = padding.Top
                        }
                    }else {
                        lWidth = width - margin.Left - margin.Right
                    }
                    top += margin.Top
                    nTop = top
                    nLeft = left + margin.Left
                    nWidth = lWidth
                    top += cHeight + margin.Bottom
                }
                if cLeft != nLeft || cTop != nTop || cWidth != nWidth || cHeight != nHeight {
                    view.Location = CreatePoint(nLeft, nTop)
                    view.Size = CreateSize(nWidth, nHeight)
                    //reset = true
                }
                vPos += 1
            }
        }
    }
}

/*
* 更新页的布局
* tabView:多页夹
* tabPage:页
* left:左侧坐标
* top:上方坐标
* width:宽度
* height:高度
* tw:页头按钮的宽度
* th:页头按钮的高度
*/
func UpdataPageLayout(tabView *FCView, tabPage *FCView, left float64, top float64, width float64, height float64, tw float64, th float64) {
    newBounds := CreateRect(0, 0, 0, 0)
    inTabPage := tabPage.GetTabPage()
    inTabView := tabView.GetTabView()
    headerButton := inTabPage.GetHeaderButton()
    if inTabView.Layout == "bottom" {
        newBounds.Left = 0
        newBounds.Top = 0
        newBounds.Right = width
        newBounds.Bottom = height - th
        headerButton.Location = CreatePoint(left, height - th)
    } else if inTabView.Layout == "left"{
        newBounds.Left = tw
        newBounds.Top = 0
        newBounds.Right = width
        newBounds.Bottom = height
        headerButton.Location = CreatePoint(0, top)
    } else if inTabView.Layout == "right" {
        newBounds.Left = 0
        newBounds.Top = 0
        newBounds.Right = width - tw
        newBounds.Bottom = height
        headerButton.Location = CreatePoint(width - tw, top)
    } else if inTabView.Layout == "top" {
        newBounds.Left = 0
        newBounds.Top = th
        newBounds.Right = width
        newBounds.Bottom = height
        headerButton.Location = CreatePoint(left, 0)
    }
    tabPage.Location = CreatePoint(newBounds.Left, newBounds.Top)
    tabPage.Size = CreateSize(newBounds.Right - newBounds.Left, newBounds.Bottom - newBounds.Top)
}

/*
* 更新多页夹的布局
* tabView:多页夹
*/
func UpdateTabLayout(tabView *FCView) {
    width := tabView.Size.Cx
    height := tabView.Size.Cy
    left := 0.0
    top := 0.0
    inTabView := tabView.GetTabView()
    if len(inTabView.TabPages) > 0{
        for i := 0; i < len(inTabView.TabPages); i++ {
            tabPage := inTabView.TabPages[i]
            inTabPage := tabPage.GetTabPage()
            headerButton := inTabPage.GetHeaderButton()
            if headerButton.Visible {
                tw := headerButton.Size.Cx
                th := headerButton.Size.Cy
                UpdataPageLayout(tabView, tabPage, left, top, width, height, tw, th)
                left += tw
                top += th
            } else {
                tabPage.Visible = false
            }
        }
    }
}

/*
* 重置分割线的布局
* split:分割视图
*/
func ResetSplitLayoutDiv(split *FCView){
    inSplit := split.GetSplitDiv()
    splitRect := CreateRect(0, 0, 0, 0)
    width := split.Size.Cx
    height := split.Size.Cy
    fRect := CreateRect(0, 0, 0, 0)
    sRect := CreateRect(0, 0, 0, 0)
    splitter := inSplit.GetSplitter()
    splitterSize := CreateSize(0, 0)
    if splitter.Visible {
        splitterSize.Cx = splitter.Size.Cx
        splitterSize.Cy = splitter.Size.Cy
    }
    layoutStyle := inSplit.LayoutStyle
    if layoutStyle == "bottomtotop" {
        if inSplit.SplitMode == "absolutesize" || inSplit.OldSize.Cy == 0 {
            splitRect.Left = 0
            splitRect.Top = height - (inSplit.OldSize.Cy - splitter.Location.Y)
            splitRect.Right = width
            splitRect.Bottom = splitRect.Top + splitterSize.Cy
        }else if inSplit.SplitMode == "percentsize" {
            splitRect.Left = 0
            if inSplit.SplitPercent == -1 {
                inSplit.SplitPercent = splitter.Location.Y / inSplit.OldSize.Cy
            }
            splitRect.Top = height * inSplit.SplitPercent
            splitRect.Right = width
            splitRect.Bottom = splitRect.Top + splitterSize.Cy
        }
        fRect.Left = 0
        fRect.Top = splitRect.Bottom
        fRect.Right = width
        fRect.Bottom = height
        sRect.Left = 0
        sRect.Top = 0
        sRect.Right = width
        sRect.Bottom = splitRect.Top
    }else if layoutStyle == "lefttoright" {
        if inSplit.SplitMode == "absolutesize" || inSplit.OldSize.Cx == 0 {
            splitRect.Left = splitter.Location.X
            splitRect.Top = 0
            splitRect.Right = splitRect.Left + splitterSize.Cx
            splitRect.Bottom = height
        }else if inSplit.SplitMode == "percentsize" {
            if inSplit.SplitPercent == -1 {
                inSplit.SplitPercent = splitter.Location.X / inSplit.OldSize.Cx
            }
            splitRect.Left = width * inSplit.SplitPercent
            splitRect.Top = 0
            splitRect.Right = splitRect.Left + splitterSize.Cx
            splitRect.Bottom = height
        }
        fRect.Left = 0
        fRect.Top = 0
        fRect.Right = splitRect.Left
        fRect.Bottom = height
        sRect.Left = splitRect.Right
        sRect.Top = 0
        sRect.Right = width
        sRect.Bottom = height
    }else if layoutStyle == "righttoleft" {
        if inSplit.SplitMode == "absolutesize" || inSplit.OldSize.Cx == 0 {
            splitRect.Left = width - (inSplit.OldSize.Cx - splitter.Location.X)
            splitRect.Top = 0
            splitRect.Right = splitRect.Left + splitterSize.Cx
            splitRect.Bottom = height
        }else if inSplit.SplitMode == "percentsize" {
            if inSplit.SplitPercent == -1 {
                inSplit.SplitPercent = splitter.Location.X / inSplit.OldSize.Cx
            }
            splitRect.Left = width * inSplit.SplitPercent
            splitRect.Top = 0
            splitRect.Right = splitRect.Left + splitterSize.Cx
            splitRect.Bottom = height
        }
        fRect.Left = splitRect.Right
        fRect.Top = 0
        fRect.Right = width
        fRect.Bottom = height
        sRect.Left = 0
        sRect.Top = 0
        sRect.Right = splitRect.Left
        sRect.Bottom = height
    }else if layoutStyle == "toptobottom" {
        if inSplit.SplitMode == "absolutesize" || inSplit.OldSize.Cy == 0 {
            splitRect.Left = 0
            splitRect.Top = splitter.Location.Y
            splitRect.Right = width
            splitRect.Bottom = splitRect.Top + splitterSize.Cy
        }else if inSplit.SplitMode == "percentsize" {
            splitRect.Left = 0
            if inSplit.SplitPercent == -1{
                inSplit.SplitPercent = splitter.Location.Y / inSplit.OldSize.Cy
            }
            splitRect.Top = height * inSplit.SplitPercent
            splitRect.Right = width
            splitRect.Bottom = splitRect.Top + splitterSize.Cy
        }
        fRect.Left = 0
        fRect.Top = 0
        fRect.Right = width
        fRect.Bottom = splitRect.Top
        sRect.Left = 0
        sRect.Top = splitRect.Bottom
        sRect.Right = width
        sRect.Bottom = height
    }
    if splitter.Visible {
        spRect := CreateRect(splitter.Location.X, splitter.Location.Y, splitter.Location.X + splitter.Size.Cx, splitter.Location.Y + splitter.Size.Cy)
        if spRect.Left != splitRect.Left || spRect.Top != splitRect.Top || spRect.Right != splitRect.Right || spRect.Bottom != splitRect.Bottom {
            splitter.Location = CreatePoint(splitRect.Left, splitRect.Top)
            splitter.Size = CreateSize(splitRect.Right - splitRect.Left, splitRect.Bottom - splitRect.Top)
            //reset = true
        }
    }
    FirstView := inSplit.GetFirstView()
    fcRect := CreateRect(FirstView.Location.X, FirstView.Location.Y, FirstView.Location.X + FirstView.Size.Cx, FirstView.Location.Y + FirstView.Size.Cy)
    if fcRect.Left != fRect.Left || fcRect.Top != fRect.Top || fcRect.Right != fRect.Right || fcRect.Bottom != fRect.Bottom {
        //reset = true
        FirstView.Location = CreatePoint(fRect.Left, fRect.Top)
        FirstView.Size = CreateSize(fRect.Right - fRect.Left, fRect.Bottom - fRect.Top)
    }
    SecondView := inSplit.GetSecondView()
    scRect := CreateRect(SecondView.Location.X, SecondView.Location.Y, SecondView.Location.X + SecondView.Size.Cx, SecondView.Location.Y + SecondView.Size.Cy)
    if scRect.Left != sRect.Left || scRect.Top != sRect.Top || scRect.Right != sRect.Right || scRect.Bottom != sRect.Bottom{
        //reset = true
        SecondView.Location = CreatePoint(sRect.Left, sRect.Top)
        SecondView.Size = CreateSize(sRect.Right - sRect.Left, sRect.Bottom - sRect.Top)
    }
    inSplit.OldSize = CreateSize(width, height)
}

/*
* 添加页
* tabView:多页夹
* tabPage:页
* tabButton:页头按钮
*/
func AddTabPage(tabView *FCView, tabPage *FCView, tabButton *FCView) {
    inTabPage := tabPage.GetTabPage()
    inTabView := tabView.GetTabView()
    inTabPage.SetHeaderButton(tabButton)
    tabPage.SetParent(tabView)
    tabPage.SetPaint(tabView.GetPaint())
    tabButton.SetParent(tabView)
    tabButton.SetPaint(tabView.GetPaint())
    inTabView.TabPages = append(inTabView.TabPages, tabPage)
    tabView.Views = append(tabView.Views, tabPage)
    tabView.Views = append(tabView.Views, tabButton)
}

/*
* 移除页
* tabView:多页夹
* tabPage:页
*/
func RemoveTabPage(tabView *FCView, pageOrButton *FCView) {
    inTabView := tabView.GetTabView()
    if len(inTabView.TabPages) > 0{
        for i := 0; i < len(inTabView.TabPages); i++ {
            tabPage := inTabView.TabPages[i]
            if tabPage.GetTabPage().GetHeaderButton() == pageOrButton || tabPage == pageOrButton {
                inTabView.TabPages = append(inTabView.TabPages[:i], inTabView.TabPages[i + 1:]...)
                RemoveViewFromParent(tabView, tabPage.GetTabPage().GetHeaderButton())
                RemoveViewFromParent(tabView, tabPage)
                break
            }
        }
    }
    if len(inTabView.TabPages) > 0{
        SelectTabPage(tabView, inTabView.TabPages[0])
    }
    UpdateTabLayout(tabView)
}

/*
* 选中页
* tabView:多页夹
* tabPage:页
*/
func SelectTabPage(tabView *FCView, tabPage *FCView) {
    inTabView := tabView.GetTabView()
    if len(tabView.Views) > 0{
        for i := 0; i < len(inTabView.TabPages); i++ {
            tp := inTabView.TabPages[i]
            if tp == tabPage {
                tp.Visible = true
            } else {
                tp.Visible = false
            }
        }
    }
    UpdateTabLayout(tabView)
}

/*
* 重绘多页加
* tabView:多页夹
* paint:绘图对象
* clipRect:裁剪区域
*/
func DrawTabViewBorder(tabView *FCView, paint *FCPaint, clipRect FCRect) {
    inTabView := tabView.GetTabView()
    if inTabView.UnderLineColor != "none" {
        if len(tabView.Views) > 0{
            for i := 0; i < len(inTabView.TabPages); i++ {
                tp := inTabView.TabPages[i]
                if tp.Visible {
                    inTabPage := tp.GetTabPage()
                    headerButton := inTabPage.GetHeaderButton()
                    location := CreatePoint(headerButton.Location.X, headerButton.Location.Y)
                    size := headerButton.Size
                    if inTabView.UseAnimation {
                        if inTabView.UnderPoint.X != 0 && inTabView.UnderPoint.Y != 0 {
                            location.X = inTabView.UnderPoint.X
                            location.Y = inTabView.UnderPoint.Y
                        }
                    }
                    if inTabView.Layout == "bottom" {
                        paint.FillRect(inTabView.UnderLineColor, location.X, location.Y, location.X + size.Cx, location.Y + inTabView.UnderLineSize)
                    } else if inTabView.Layout == "left" {
                        paint.FillRect(inTabView.UnderLineColor, location.X + size.Cx - inTabView.UnderLineSize, location.Y, location.X + size.Cx, location.Y + size.Cy)
                    } else if inTabView.Layout == "top" {
                        paint.FillRect(inTabView.UnderLineColor, location.X, location.Y + size.Cy - inTabView.UnderLineSize, location.X + size.Cx, location.Y + size.Cy)
                    }else if inTabView.Layout == "right"{
                        paint.FillRect(inTabView.UnderLineColor, location.X, location.Y, location.X + inTabView.UnderLineSize, location.Y + size.Cy)
                    }
                    break
                }
            }
        }
    }
}

/*
* 获取总的偏移量
* node:树节点
*/
func GetTotalIndent(node *FCTreeNode)(float64) {
    if node.GetParentNode().IsNotEmpty {
        return node.Indent + GetTotalIndent(node.GetParentNode())
    } else {
        return node.Indent
    }
}

/*
* 绘制单元格
* tree:树
* row:行
* column:列
* node:节点
* paint:绘图对象
* left:左侧坐标
* top:上方坐标
* right:右侧坐标
* bottom:下方坐标
*/
func DrawTreeNode(tree *FCView, row *FCTreeRow, column *FCTreeColumn, node *FCTreeNode, paint *FCPaint, left float64, top float64, right float64, bottom float64) {
    inTree := tree.GetTree()
    if node.BackColor != "none" {
        paint.FillRect(node.BackColor, left, top, right, bottom)
    }
    if len(node.Value) > 0 {
        tSize := paint.TextSize(node.Value, node.Font)
        tLeft := left + 2 + GetTotalIndent(node)
        wLeft := tLeft
        cR := inTree.CheckBoxWidth / 3
        if inTree.ShowCheckBox {
            wLeft += inTree.CheckBoxWidth
            if node.Checked {
                paint.FillRect(node.TextColor, tLeft + (inTree.CheckBoxWidth - cR) / 2, top + (inTree.RowHeight - cR) / 2, tLeft + (inTree.CheckBoxWidth + cR) / 2, top + (inTree.RowHeight + cR) / 2)
            } else {
                paint.DrawRect(node.TextColor, 1, 0, tLeft + (inTree.CheckBoxWidth - cR) / 2, top + (inTree.RowHeight - cR) / 2, tLeft + (inTree.CheckBoxWidth + cR) / 2, top + (inTree.RowHeight + cR) / 2)
            }
        }
        if len(node.ChildNodes) > 0 {
            var drawPoints []FCPoint
            if node.Collapsed {
                drawPoints = append(drawPoints, CreatePoint(wLeft + (inTree.CollapsedWidth + cR) / 2, top + inTree.RowHeight / 2))
				drawPoints = append(drawPoints, CreatePoint(wLeft + (inTree.CollapsedWidth - cR) / 2, top + (inTree.RowHeight - cR) / 2))
				drawPoints = append(drawPoints, CreatePoint(wLeft + (inTree.CollapsedWidth - cR) / 2, top + (inTree.RowHeight + cR) / 2))
            } else {
                drawPoints = append(drawPoints, CreatePoint(wLeft + (inTree.CollapsedWidth - cR) / 2, top + (inTree.RowHeight - cR) / 2))
				drawPoints = append(drawPoints, CreatePoint(wLeft + (inTree.CollapsedWidth + cR) / 2, top + (inTree.RowHeight - cR) / 2))
				drawPoints = append(drawPoints, CreatePoint(wLeft + inTree.CollapsedWidth / 2, top + (inTree.RowHeight + cR) / 2))
            }
            paint.FillPolygon(node.TextColor, drawPoints)
            wLeft += inTree.CollapsedWidth
        }
        
        if tSize.Cx > column.Width{
            paint.DrawTextAutoEllipsis(node.Value, node.TextColor, node.Font, wLeft, top + inTree.RowHeight / 2 - tSize.Cy / 2, wLeft + column.Width, top + inTree.RowHeight / 2 - tSize.Cy / 2)
        } else {
            paint.DrawText(node.Value, node.TextColor, node.Font, wLeft, top + inTree.RowHeight / 2 - tSize.Cy / 2)
        }
    }
}

/*
* 绘制树
* tree:树
* paint:绘图对象
* clipRect:裁剪区域
*/
func DrawTree(tree *FCView, paint *FCPaint, clipRect FCRect) {
    inTree := tree.GetTree()
    cTop := -tree.ScrollV + inTree.HeaderHeight
    //绘制行
    colLeft := 0.0
    if len(inTree.Columns) > 0{
        for i := 0; i < len(inTree.Columns); i++ {
            if(len(inTree.Columns[i].WidthStr) > 0){
                newWidthStr := strings.Replace(inTree.Columns[i].WidthStr, "(", "", -1)
                inTree.Columns[i].Width = ConvertToFloat64(newWidthStr) * tree.Size.Cx / 100
            }
            colRect := CreateRect(colLeft, 0, colLeft + inTree.Columns[i].Width, inTree.HeaderHeight)
            inTree.Columns[i].Bounds = colRect
            inTree.Columns[i].Index = i
            colLeft += inTree.Columns[i].Width
        }
    }
    UpdateTreeRowIndex(tree)
    if len(inTree.Rows) > 0{
        for i := 0; i < len(inTree.Rows); i++ {
            row := inTree.Rows[i]
            if row.Visible {
                rTop := cTop
                rBottom := cTop + inTree.RowHeight
                if rBottom >= 0 && cTop <= tree.Size.Cy{
                    for j := 0; j < len(row.Cells); j++ {
                        node := row.Cells[j]
                        treeColumn := node.GetColumn()
                        if !treeColumn.IsNotEmpty {
                            treeColumn = inTree.Columns[j]
                        }
                        if treeColumn.Visible {
                            nodeWidth := treeColumn.Width
                            nodeHeight := inTree.RowHeight
                            cRect := CreateRect(treeColumn.Bounds.Left - tree.ScrollH, rTop, treeColumn.Bounds.Left + nodeWidth - tree.ScrollH, rTop + nodeHeight)
                            if cRect.Right >= 0 && cRect.Left < tree.Size.Cx {
                                if inTree.OnPaintTreeNode != nil{
                                    inTree.OnPaintTreeNode(tree, row, treeColumn, node, paint, cRect.Left, cRect.Top, cRect.Right, cRect.Bottom)
                                }else if paint.OnPaintTreeNode != nil{
                                    paint.OnPaintTreeNode(tree, row, treeColumn, node, paint, cRect.Left, cRect.Top, cRect.Right, cRect.Bottom)
                                }else{
                                    DrawTreeNode(tree, row, treeColumn, node, paint, cRect.Left, cRect.Top, cRect.Right, cRect.Bottom)
                                }
                            }
                        }
                    }
                }
                if cTop > tree.Size.Cy {
                    break
                }
                cTop += inTree.RowHeight
            }
        }
    }
}

/*
* 绘制滚动条
* tree:树
* paint:绘图对象
* clipRect:裁剪区域
*/
func DrawTreeScrollBar(tree *FCView, paint *FCPaint, clipRect FCRect) {
    tree.HScrollIsVisible = false
    tree.VScrollIsVisible = false
    inTree := tree.GetTree()
    if tree.ShowHScrollBar {
        contentWidth := GetTreeContentWidth(tree)
        if contentWidth > 0 && contentWidth > tree.Size.Cx {
            sLeft := tree.ScrollH / contentWidth * tree.Size.Cx
            sRight := (tree.ScrollH + tree.Size.Cx) / contentWidth * tree.Size.Cx
            if sRight - sLeft < tree.ScrollSize {
                sRight = sLeft + tree.ScrollSize
            }
            if paint.GetTouchMoveView() == tree && (tree.HoverScrollHButton || tree.DownScrollHButton) {
                paint.FillRect(tree.ScrollBarHoveredColor, sLeft, tree.Size.Cy - tree.ScrollSize, sRight, tree.Size.Cy)
            }else {
                paint.FillRect(tree.ScrollBarColor, sLeft, tree.Size.Cy - tree.ScrollSize, sRight, tree.Size.Cy)
            }
            tree.HScrollIsVisible = true
        }
    }
    if tree.ShowVScrollBar{
        contentHeight := GetTreeContentHeight(tree)
        if contentHeight > 0 && contentHeight > tree.Size.Cy {
            sTop := inTree.HeaderHeight + tree.ScrollV / contentHeight * (tree.Size.Cy - inTree.HeaderHeight - tree.ScrollSize)
            sBottom := sTop + ((tree.Size.Cy - inTree.HeaderHeight)) / contentHeight * (tree.Size.Cy - inTree.HeaderHeight - tree.ScrollSize)
            if sBottom - sTop < tree.ScrollSize {
                sBottom = sTop + tree.ScrollSize
            }
            if paint.GetTouchMoveView() == tree && (tree.HoverScrollVButton || tree.DownScrollVButton) {
                paint.FillRect(tree.ScrollBarHoveredColor, tree.Size.Cx - tree.ScrollSize, sTop, tree.Size.Cx, sBottom)
            } else {
                paint.FillRect(tree.ScrollBarColor, tree.Size.Cx - tree.ScrollSize, sTop, tree.Size.Cx, sBottom)
            }
            tree.VScrollIsVisible = true
        }
    }
}

/*
* 获取内容的宽度
* tree:树
*/
func GetTreeContentWidth(tree *FCView)(float64){
    inTree := tree.GetTree()
    cWidth := 0.0
    if len(inTree.Columns) > 0{
        for i := 0; i < len(inTree.Columns); i++ {
            if inTree.Columns[i].Visible {
                cWidth += inTree.Columns[i].Width
            }
        }
    }
    return cWidth
}

/*
* 获取内容的高度
* tree:树
*/
func GetTreeContentHeight(tree *FCView)(float64){
    inTree := tree.GetTree()
    cHeight := 0.0
    if len(inTree.Rows) > 0{
        for i := 0; i < len(inTree.Rows); i++ {
            if inTree.Rows[i].Visible {
                cHeight += inTree.RowHeight
            }
        }
    }
    return cHeight
}

/*
* 树的鼠标移动方法
* tree: 树
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
*/
func TouchMoveTree(tree *FCView, firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint) {
    inTree := tree.GetTree()
    tree.HoverScrollHButton = false
    tree.HoverScrollVButton = false
    mp := CreatePoint(firstPoint.X, firstPoint.Y)
    paint := tree.GetPaint()
    if firstTouch {
        if tree.ShowHScrollBar || tree.ShowVScrollBar {
            if (tree.DownScrollHButton) {
                contentWidth := GetTreeContentWidth(tree)
                subX := (mp.X - tree.StartPoint.X) / tree.Size.Cx * contentWidth
                newScrollH := tree.StartScrollH + subX
                if newScrollH < 0 {
                    newScrollH = 0
                } else if newScrollH > contentWidth - tree.Size.Cx {
                    newScrollH = contentWidth - tree.Size.Cx
                }
                tree.ScrollH = newScrollH
                paint.CancelClick = true
                return
            } else if tree.DownScrollVButton {
                contentHeight := GetTreeContentHeight(tree)
                subY := (mp.Y - tree.StartPoint.Y) / (tree.Size.Cy - inTree.HeaderHeight - tree.ScrollSize) * contentHeight
                newScrollV := tree.StartScrollV + subY
                if newScrollV < 0 {
                    newScrollV = 0
                } else if newScrollV > contentHeight - (tree.Size.Cy - inTree.HeaderHeight - tree.ScrollSize) {
                    newScrollV = contentHeight - (tree.Size.Cy - inTree.HeaderHeight - tree.ScrollSize)
                }
                tree.ScrollV = newScrollV
                paint.CancelClick = true
                return
            }
        }
        if tree.AllowDragScroll {
            contentWidth := GetTreeContentWidth(tree)
            if contentWidth > tree.Size.Cx {
                subX := tree.StartPoint.X - mp.X
                newScrollH := tree.StartScrollH + subX
                if newScrollH < 0 {
                    newScrollH = 0
                } else if newScrollH > contentWidth - tree.Size.Cx {
                    newScrollH = contentWidth - tree.Size.Cx
                }
                tree.ScrollH = newScrollH
                if subX > 5 || subX < -5 {
                    paint.CancelClick = true
                }
            }
            contentHeight := GetTreeContentHeight(tree)
            if contentHeight > tree.Size.Cy {
                subY := tree.StartPoint.Y - mp.Y
                newScrollV := tree.StartScrollV + subY
                if newScrollV < 0 {
                    newScrollV = 0
                } else if newScrollV > contentHeight - (tree.Size.Cy - inTree.HeaderHeight - tree.ScrollSize) {
                    newScrollV = contentHeight - (tree.Size.Cy - inTree.HeaderHeight - tree.ScrollSize)
                }
                tree.ScrollV = newScrollV
                if subY > 5 || subY < -5 {
                    paint.CancelClick = true
                }
            }
        }
    } else {
        if tree.ShowHScrollBar {
            contentWidth := GetTreeContentWidth(tree)
            if contentWidth > 0 && contentWidth > tree.Size.Cx {
                sLeft := tree.ScrollH / contentWidth * tree.Size.Cx
                sRight := (tree.ScrollH + tree.Size.Cx) / contentWidth * tree.Size.Cx
                if sRight - sLeft < tree.ScrollSize {
                    sRight = sLeft + tree.ScrollSize
                }
                if mp.X >= sLeft && mp.X <= sRight && mp.Y >= tree.Size.Cy - tree.ScrollSize && mp.Y <= tree.Size.Cy {
                    tree.HoverScrollHButton = true
                    return
                } else {
                    tree.HoverScrollHButton = false
                }
            }
        }
        if tree.ShowVScrollBar {
            contentHeight := GetTreeContentHeight(tree)
            if contentHeight > 0 && contentHeight > tree.Size.Cy{
                sTop := inTree.HeaderHeight + tree.ScrollV / contentHeight * (tree.Size.Cy - inTree.HeaderHeight - tree.ScrollSize)
                sBottom := inTree.HeaderHeight + (tree.ScrollV + (tree.Size.Cy - inTree.HeaderHeight - tree.ScrollSize)) / contentHeight * (tree.Size.Cy - inTree.HeaderHeight - tree.ScrollSize)
                if sBottom - sTop < tree.ScrollSize {
                    sBottom = sTop + tree.ScrollSize
                }
                if mp.X >= tree.Size.Cx - tree.ScrollSize && mp.X <= tree.Size.Cx && mp.Y >= sTop && mp.Y <= sBottom {
                    tree.HoverScrollVButton = true
                    return
                } else {
                    tree.HoverScrollVButton = false
                }
            }
        }
    }
}

/*
* 树的鼠标按下方法
* tree: 树
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
* clicks:点击次数
*/
func TouchDownTree(tree *FCView, firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint, clicks int) {
    inTree := tree.GetTree()
    mp := CreatePoint(firstPoint.X, firstPoint.Y)
    tree.StartPoint = mp
    tree.DownScrollHButton = false
    tree.DownScrollVButton = false
    if tree.ShowHScrollBar {
        contentWidth := GetTreeContentWidth(tree)
        if contentWidth > 0 && contentWidth > tree.Size.Cx {
            sLeft := tree.ScrollH / contentWidth * tree.Size.Cx
            sRight := (tree.ScrollH + tree.Size.Cx) / contentWidth * tree.Size.Cx
            if sRight - sLeft < tree.ScrollSize {
                sRight = sLeft + tree.ScrollSize
            }
            if mp.X >= sLeft && mp.X <= sRight && mp.Y >= tree.Size.Cy - tree.ScrollSize && mp.Y <= tree.Size.Cy {
                tree.DownScrollHButton = true
                tree.StartScrollH = tree.ScrollH
                return
            }
        }
    }
    if tree.ShowVScrollBar {
        contentHeight := GetTreeContentHeight(tree)
        if contentHeight > 0 && contentHeight > tree.Size.Cy {
            sTop := inTree.HeaderHeight + tree.ScrollV / contentHeight * (tree.Size.Cy - inTree.HeaderHeight - tree.ScrollSize)
            sBottom := inTree.HeaderHeight + (tree.ScrollV + (tree.Size.Cy - inTree.HeaderHeight - tree.ScrollSize)) / contentHeight * (tree.Size.Cy - inTree.HeaderHeight - tree.ScrollSize)
            if sBottom - sTop < tree.ScrollSize {
                sBottom = sTop + tree.ScrollSize
            }
            if mp.X >= tree.Size.Cx - tree.ScrollSize && mp.X <= tree.Size.Cx && mp.Y >= sTop && mp.Y <= sBottom {
                tree.DownScrollVButton = true
                tree.StartScrollV = tree.ScrollV
                return
            }
        }
    }
    if tree.AllowDragScroll {
        tree.StartScrollH = tree.ScrollH
        tree.StartScrollV = tree.ScrollV
    }
}

/*
* 表格的鼠标抬起方法
* tree: 树
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
* clicks:点击次数
*/
func TouchUpTree(tree *FCView, firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint, clicks int) {
    tree.HoverScrollHButton = false
    tree.HoverScrollVButton = false
    tree.DownScrollHButton = false
    tree.DownScrollVButton = false
    if tree.GetPaint().CancelClick{
        return
    }
    inTree := tree.GetTree()
    cLeft := -tree.ScrollH
    cTop := -tree.ScrollV + inTree.HeaderHeight
    if len(inTree.Rows) > 0{
        for i := 0; i < len(inTree.Rows); i++ {
            row := inTree.Rows[i]
            if row.Visible {
                if firstPoint.Y >= cTop && firstPoint.Y <= cTop + inTree.RowHeight {
                    node := row.Cells[0]
                    tLeft := cLeft + 2 + GetTotalIndent(node)
                    wLeft := tLeft
                    if inTree.ShowCheckBox {
                        wLeft += inTree.CheckBoxWidth
                        if firstPoint.X < wLeft {
                            CheckOrUnCheckTreeNode(node, !node.Checked)
                            InvalidateView(tree)
                            break
                        }
                    }
                    if len(node.ChildNodes) > 0 {
                        wLeft += inTree.CollapsedWidth
                        if firstPoint.X < wLeft {
                            node.Collapsed = !node.Collapsed
                            HideOrShowTreeNode(node, !node.Collapsed)
                            InvalidateView(tree)
                            break
                        }
                    }
                    if inTree.OnClickTreeNode != nil{
                        inTree.OnClickTreeNode(tree, node, firstTouch, firstPoint, secondTouch, secondPoint, clicks)
                    }else if tree.GetPaint().OnClickTreeNode != nil{
					    tree.GetPaint().OnClickTreeNode(tree, node, firstTouch, firstPoint, secondTouch, secondPoint, clicks)
                    }
                }
                cTop += inTree.RowHeight
            }
        }
    }
}

/*
* 更新行的索引
* tree:树
*/
func UpdateTreeRowIndex(tree *FCView) {
    inTree := tree.GetTree()
    if len(inTree.Rows) > 0{
        for i := 0; i < len(inTree.Rows); i++ {
            inTree.Rows[i].Index = i
        }
    }
}

/*
* 获取最后一行的索引
* node:树节点
*/
func GetTreeLastNodeRowIndex(node *FCTreeNode)(int) {
    nodeRow := node.GetRow()
    rowIndex := nodeRow.Index
    if len(node.ChildNodes) > 0{
        for i := 0; i < len(node.ChildNodes); i++ {
            rIndex := GetTreeLastNodeRowIndex(node.ChildNodes[i])
            if rowIndex < rIndex {
                rowIndex = rIndex
            }
        }
    }
    return rowIndex
}

/*
* 添加节点
* tree:树
* node:要添加的节点
* parentNode:父节点
*/
func AppendTreeNode(tree *FCView, node *FCTreeNode, parentNode *FCTreeNode) {
    inTree := tree.GetTree()
    if !parentNode.IsNotEmpty {
        newRow := CreateTreeRow()
        inTree.Rows = append(inTree.Rows, newRow)
        node.SetRow(newRow)
        newRow.Cells = append(newRow.Cells, node)
        inTree.ChildNodes = append(inTree.ChildNodes, node)
    } else {
        newRow := CreateTreeRow()
        if len(parentNode.ChildNodes) == 0 {
            index := parentNode.GetRow().Index + 1
            newRows := inTree.Rows[:index]
            newRows = append(newRows, newRow)
            newRows = append(newRows, inTree.Rows[index:]...)
            inTree.Rows = newRows
        } else {
            index := GetTreeLastNodeRowIndex(parentNode) + 1
            newRows := inTree.Rows[:index]
            newRows = append(newRows, newRow)
            newRows = append(newRows, inTree.Rows[index:]...)
            inTree.Rows = newRows
        }
        node.SetParentNode(parentNode)
        node.Indent = inTree.Indent
        node.SetRow(newRow)
        newRow.Cells = append(newRow.Cells, node)
        parentNode.ChildNodes = append(parentNode.ChildNodes, node)
        if parentNode.Collapsed {
            newRow.Visible = false
        }
    }
    UpdateTreeRowIndex(tree)
}

/*
* 移除节点
* tree:树
* node:要添加的节点
*/
func RemoveTreeNode (tree *FCView, node *FCTreeNode) {
    inTree := tree.GetTree()
    //移除相互关系
    if !node.IsNotEmpty {
        nodesSize := len(inTree.ChildNodes)
        if nodesSize > 0{
            for i := 0; i < nodesSize; i++ {
                if inTree.ChildNodes[i] == node {
                    inTree.ChildNodes = append(inTree.ChildNodes[:i], inTree.ChildNodes[i + 1:]...)
                    break
                }
            }
        }
    } else {
        parentNode := node.GetParentNode()
        nodesSize := len(parentNode.ChildNodes)
        if nodesSize > 0{
            for i := 0; i < nodesSize; i++ {
                if parentNode.ChildNodes[i] == node {
                    parentNode.ChildNodes = append(parentNode.ChildNodes[:i], parentNode.ChildNodes[i + 1:]...)
                    break
                }
            }
        }
    }
    //移除行
    nodeRow := node.GetRow()
    inTree.Rows = append(inTree.Rows[:nodeRow.Index], inTree.Rows[nodeRow.Index + 1:]...)
    UpdateTreeRowIndex(tree)
}

/*
* 展开或折叠节点
* node:节点
* visible:是否可见
*/
func HideOrShowTreeNode(node *FCTreeNode, visible bool) {
    if len(node.ChildNodes) > 0 {
        for i := 0; i < len(node.ChildNodes); i++ {
            row := node.ChildNodes[i].GetRow()
            row.Visible = visible
            HideOrShowTreeNode(node.ChildNodes[i], visible)
        }
    }
}

/*
* 选中或反选节点
* node:节点
* checked:是否选中
*/
func CheckOrUnCheckTreeNode(node *FCTreeNode, checked bool) {
    node.Checked = checked
    if len(node.ChildNodes) > 0{
        for i := 0; i < len(node.ChildNodes); i++ {
            CheckOrUnCheckTreeNode(node.ChildNodes[i], checked)
        }
    }
}

/*
* 展开树的节点
* tree:树
*/
func ExpendTree(tree *FCView) {
    inTree := tree.GetTree()
    if len(inTree.ChildNodes) > 0{
        for i := 0; i < len(inTree.ChildNodes); i++ {
            inTree.ChildNodes[i].Collapsed = false
            HideOrShowTreeNode(inTree.ChildNodes[i], true)
        }
    }
}

/*
* 折叠树的节点
* tree:树
*/
func CollapseTree(tree *FCView) {
    inTree := tree.GetTree()
    if len(inTree.ChildNodes) > 0{
        for i := 0; i < len(inTree.ChildNodes); i++ {
            inTree.ChildNodes[i].Collapsed = true
            HideOrShowTreeNode(inTree.ChildNodes[i], false)
        }
    }
}

/*
* 树的鼠标滚轮方法
* tree:树
* delta:滚轮值
*/
func TouchWheelTree(tree *FCView, delta int) {
    inTree := tree.GetTree()
    oldScrollV := tree.ScrollV
    if delta < 0 {
        oldScrollV -= 20
    } else if delta > 0 {
        oldScrollV += 20
    }
    contentHeight := GetTreeContentHeight(tree)
    if contentHeight < tree.Size.Cy {
        tree.ScrollV = 0
    } else {
        if oldScrollV < 0 {
            oldScrollV = 0
        } else if oldScrollV > contentHeight - tree.Size.Cy + inTree.HeaderHeight + tree.ScrollSize {
            oldScrollV = contentHeight - tree.Size.Cy + inTree.HeaderHeight + tree.ScrollSize
        }
        tree.ScrollV = oldScrollV
    }
}

/*
 * 自动适应位置和大小
 * menu:菜单
 */
func AdjustMenu(menu *FCView) {
    ResetLayoutDiv(menu)
    inMenu := menu.GetMenu()
    if inMenu.AutoSize {
        contentHeight := GetDivContentHeight(menu)
        maximumHeight := menu.MaximumSize.Cy
        menu.Size.Cy = math.Min(contentHeight, maximumHeight)
    }
    mPoint := CreatePoint(menu.Location.X, menu.Location.Y)
    mSize := menu.Size
    paint := menu.GetPaint()
    nSize := CreateSize(paint.Size.Cx / paint.ScaleFactorX, paint.Size.Cy / paint.ScaleFactorY)
    if mPoint.X < 0 {
        mPoint.X = 0
    }
    if mPoint.Y < 0 {
        mPoint.Y = 0
    }
    if mPoint.X + mSize.Cx > nSize.Cx {
        mPoint.X = nSize.Cx - mSize.Cx
    }
    if mPoint.Y + mSize.Cy > nSize.Cy {
        mPoint.Y = nSize.Cy - mSize.Cy
    }
    menu.Location = mPoint
    menu.ScrollV = 0
}

/*
 * 添加菜单项
 * item:菜单项
 * menu:菜单
 */
func AddMenuItem(item *FCView, menu *FCView) {
    AddViewToParent(item, menu)
    inMenu := menu.GetMenu()
    item.GetMenuItem().SetParentMenu(menu)
    inMenu.Items = append(inMenu.Items, item)
}

/*
 * 添加菜单项
 * item:菜单项
 * parentItem:父菜单项
 */
func AddMenuItemToParent(item *FCView, parentItem *FCView) {
    inParentItem := parentItem.GetMenuItem()
    intItem := item.GetMenuItem()
    intItem.SetParentItem(parentItem)
    if !inParentItem.GetDropDownMenu().IsNotEmpty {
        newMenu := CreateView("menu")
        inParentItem.SetDropDownMenu(newMenu)
        AddView(inParentItem.GetDropDownMenu(), parentItem.GetPaint())
    }
    intItem.SetParentMenu(inParentItem.GetDropDownMenu())
    AddViewToParent(item, inParentItem.GetDropDownMenu())
    inParentItem.Items = append(inParentItem.Items, item)
    inParentItem.GetDropDownMenu().GetMenu().Items = append(inParentItem.GetDropDownMenu().GetMenu().Items, item)
}

/*
 * 控制菜单的显示隐藏
 * paint:绘图对象
 */
func CheckShowMenu(paint *FCPaint) {
    paintAll := false
    clickItem := false
    if len(paint.Views) > 0{
        for i := 0; i < len(paint.Views); i++ {
            view := paint.Views[i]
            if view.ViewType == "menu" {
                if view.Visible {
                    if view == paint.GetTouchDownView() {
                        clickItem = true
                    }
                    if len(view.GetMenu().Items) > 0{
                        for j := 0; j < len(view.GetMenu().Items); j++ {
                            item := view.GetMenu().Items[j]
                            if item == paint.GetTouchDownView() {
                                clickItem = true
                                break
                            }
                        }
                    }
                }
            }
        }
        if (!clickItem) {
            for i := 0; i < len(paint.Views); i++ {
                view := paint.Views[i]
                if view.ViewType == "menu" {
                    view.Visible = false
                    paintAll = true
                }
            }
        }
    }
    if paintAll {
        Invalidate(paint)
    }
}

/*
 * 关闭网格视图
 * items:菜单集合
 */
func CloseMenus(items []*FCView)(bool) {
    itemSize := len(items)
    close := false
    if itemSize > 0{
        for i := 0; i < itemSize; i++{
            item := items[i]
            subItems := item.GetMenuItem().Items
            if CloseMenus(subItems) {
                close = true
            }
            dropDownMenu := item.GetMenuItem().GetDropDownMenu()
            if (dropDownMenu.IsNotEmpty && dropDownMenu.Visible) {
                dropDownMenu.Visible = false
                close = true
            }
        }
    }
    return close
}

/*
 * 鼠标移动到菜单项
 * item 菜单项
 */
func TouchMoveMenuItem(item *FCView) {
    parentItem := item.GetMenuItem().GetParentItem()
    var items []*FCView
    if (parentItem.IsNotEmpty) {
        if (parentItem.GetMenuItem().GetDropDownMenu().IsNotEmpty) {
            items = parentItem.GetMenuItem().GetDropDownMenu().GetMenu().Items
        }
    } else {
        if (item.GetMenuItem().GetParentMenu().IsNotEmpty) {
            items = item.GetMenuItem().GetParentMenu().GetMenu().Items
        }
    }
    CloseMenus(items)
    if (len(item.GetMenuItem().Items) > 0) {
        dropDownMenu := item.GetMenuItem().GetDropDownMenu()
        //获取位置和大小
        if (dropDownMenu.IsNotEmpty && !dropDownMenu.Visible) {
            layoutStyle := dropDownMenu.GetLayoutDiv().LayoutStyle
            location := CreatePoint(ClientX(item) + item.Size.Cx, ClientY(item))
            if (layoutStyle == "lefttoright" || layoutStyle == "righttoleft") {
                location.X = ClientX(item)
                location.Y = ClientY(item) + item.Size.Cy
            }
            //设置弹出位置
            dropDownMenu.Location = location
            dropDownMenu.Visible = true
            AdjustMenu(dropDownMenu)
            Invalidate(item.GetPaint())
            return
        }
    }
    Invalidate(item.GetPaint())
}

/*
* 重绘按钮
* item:菜单项
* paint:绘图对象
* clipRect:裁剪区域
*/
func DrawMenuItem(item *FCView, paint *FCPaint, clipRect FCRect) {
    if (item == paint.GetTouchDownView()) {
        if (item.PushedColor != "none") {
            paint.FillRect(item.PushedColor, 0, 0, item.Size.Cx, item.Size.Cy)
        } else {
            if (item.BackColor != "none") {
                paint.FillRect(item.BackColor, 0, 0, item.Size.Cx, item.Size.Cy)
            }
        }
    } else if (item == paint.GetTouchMoveView()) {
        if (item.HoveredColor != "none") {
            paint.FillRect(item.HoveredColor, 0, 0, item.Size.Cx, item.Size.Cy)
        } else {
            if (item.BackColor != "none") {
                paint.FillRect(item.BackColor, 0, 0, item.Size.Cx,  item.Size.Cy)
            }
        }
    } else if (item.BackColor != "none") {
        paint.FillRect(item.BackColor, 0, 0, item.Size.Cx, item.Size.Cy)
    }
    if (item.TextColor != "none" && len(item.Text) > 0) {
        tSize := paint.TextSize(item.Text, item.Font)
        paint.DrawText(item.Text, item.TextColor, item.Font, (item.Size.Cx - tSize.Cx) / 2, (item.Size.Cy - tSize.Cy) / 2)
    }
    if (item.BorderColor != "none") {
        paint.DrawRect(item.BorderColor, item.BorderWidth, 0, 0, 0, item.Size.Cx, item.Size.Cy)
    }
    if (len(item.GetMenuItem().Items) > 0){
		tR := 5.0
        var drawPoints []FCPoint
        drawPoints = append(drawPoints, CreatePoint(item.Size.Cx - 2, item.Size.Cy / 2))
        drawPoints = append(drawPoints, CreatePoint(item.Size.Cx - 2 - tR * 2, item.Size.Cy / 2 - tR))
        drawPoints = append(drawPoints, CreatePoint(item.Size.Cx - 2 - tR * 2, item.Size.Cy / 2 + tR))
        paint.FillPolygon(item.TextColor, drawPoints)
    }
}

/*
 * 点击菜单项
 * item:菜单项
 */
func ClickMenuItem(item *FCView) {
    paintAll := false
    inItem := item.GetMenuItem()
    if inItem.GetParentMenu().IsNotEmpty {
        if inItem.GetParentMenu().GetMenu().GetComboBox().IsNotEmpty {
            index := -1
            if len(inItem.GetParentMenu().GetMenu().Items) > 0{
                for i := 0; i < len(inItem.GetParentMenu().GetMenu().Items); i++{
                    if inItem.GetParentMenu().GetMenu().Items[i] == item {
                        index = i
                        break
                    }
                }
                inItem.GetParentMenu().GetMenu().GetComboBox().GetComboBox().SelectedIndex = index
                inItem.GetParentMenu().GetMenu().GetComboBox().Text = inItem.GetParentMenu().GetMenu().Items[index].Text
                paintAll = true
            }
        }
    }
    if len(inItem.Items) == 0 {
        for i := 0; i < len(item.GetPaint().Views); i++{
            subView := item.GetPaint().Views[i]
            if subView.ViewType == "menu" {
                if subView.Visible {
                    subView.Visible = false
                    paintAll = true
                }
            }
        }
    }
    if paintAll {
        Invalidate(item.GetPaint())
    }
}

/*
* 重绘按钮
* comboBox:下拉列表
* paint:绘图对象
* clipRect:裁剪区域
*/
func DrawComboBox(comboBox *FCView, paint *FCPaint, clipRect FCRect) {
    if comboBox.BackColor != "none" {
        paint.FillRect(comboBox.BackColor, 0, 0, comboBox.Size.Cx, comboBox.Size.Cy)
    }
    if comboBox.TextColor != "none" && len(comboBox.Text) > 0 {
        tSize := paint.TextSize(comboBox.Text, comboBox.Font)
        paint.DrawText(comboBox.Text, comboBox.TextColor, comboBox.Font, 5, (comboBox.Size.Cy - tSize.Cy) / 2)
    }
    if comboBox.BorderColor != "none" {
        paint.DrawRect(comboBox.BorderColor, comboBox.BorderWidth, 0, 0, 0, comboBox.Size.Cx, comboBox.Size.Cy)
    }
    tR := 5.0
    var drawPoints []FCPoint
    drawPoints = append(drawPoints, CreatePoint(comboBox.Size.Cx - 5 - tR * 2, comboBox.Size.Cy / 2 - tR))
    drawPoints = append(drawPoints, CreatePoint(comboBox.Size.Cx - 5, comboBox.Size.Cy / 2 - tR))
    drawPoints = append(drawPoints, CreatePoint(comboBox.Size.Cx - 5 - tR, comboBox.Size.Cy / 2 + tR))
    paint.FillPolygon(comboBox.TextColor, drawPoints)
}

/*
 * 点击下拉菜单
 * comboBox:下拉菜单
 */
func ClickComboBox(comboBox *FCView) {
    showX := ClientX(comboBox)
    showY := ClientY(comboBox) + comboBox.Size.Cy
    inComboBox := comboBox.GetComboBox()
    inComboBox.GetDropDownMenu().Location = CreatePoint(showX, showY)
    inComboBox.GetDropDownMenu().Visible = true
    AdjustMenu(inComboBox.GetDropDownMenu())
    Invalidate(comboBox.GetPaint())
}

/*
* 显示或隐藏输入框
*/
func ShowOrHideInput(views []*FCView){
    viewsSize := len(views)
    if viewsSize > 0{
        for i := 0; i < viewsSize; i++ {
            view := views[i]
            paintVisible := IsPaintVisible(view)
		    if (len(view.Views) > 0) {     
			    ShowOrHideInput(view.Views)
		    }
            if(view.HasInput){
                clipRect := view.ClipRect
                if(clipRect.IsNotEmpty){
                    paint := view.GetPaint()
                    canvas := paint.Canvas
                    rect := canvas.Call("getBoundingClientRect")
                    var document js.Value = js.
                    Global().
                    Get("document")
                    newTop := rect.Get("top").Float() + document.Get("documentElement").Get("scrollTop").Float()
                    newLeft := rect.Get("left").Float() + document.Get("documentElement").Get("scrollLeft").Float()
                    relativeRect := CreateRect(newLeft + clipRect.Left * paint.ScaleFactorX, newTop + clipRect.Top * paint.ScaleFactorY, newLeft + clipRect.Right * paint.ScaleFactorX, newTop + clipRect.Bottom * paint.ScaleFactorY)
                    input := view.Input
                    input.Get("style").Set("left", ConvertFloat64ToStr(relativeRect.Left) + "px")
                    input.Get("style").Set("top", ConvertFloat64ToStr(relativeRect.Top) + "px")
                    input.Get("style").Set("width", ConvertFloat64ToStr(relativeRect.Right - relativeRect.Left) + "px")
                    input.Get("style").Set("height", ConvertFloat64ToStr(relativeRect.Bottom - relativeRect.Top) + "px")
                    input.Get("style").Set("backgroundColor", ConvertToColor(view.BackColor))
                    input.Get("style").Set("border", "1px solid " + ConvertToColor(view.BorderColor))
                    input.Get("style").Set("color", ConvertToColor(view.TextColor))
                    if paintVisible {
                        input.Get("style").Set("display", "block")
                    } else {
                        input.Get("style").Set("display", "none")
                    }
                }
            }
        }
    }
}

/*
* 计算直线参数
* mp:坐标
* x1:横坐标1
* y1:纵坐标1
* x2:横坐标2
* y2:纵坐标2
* oX:坐标起始X
* oY:坐标起始Y
*/
func LineXY(chart *FCView, x1 float64, y1 float64, x2 float64, y2 float64, oX float64, oY float64) {
    inChart := chart.GetChart()
    inChart.KChart = 0
    inChart.BChart = 0
    if (x1 - oX) != (x2 - oX) {
        inChart.KChart = ((y2 - oY) - (y1 - oY)) / ((x2 - oX) - (x1 - oX))
        inChart.BChart = (y1 - oY) - inChart.KChart * (x1 - oX)
    }
}

/*
* 判断是否选中直线
* mp:坐标
* x1:横坐标1
* y1:纵坐标1
* x2:横坐标2
* y2:纵坐标2
*/
func SelectLine(chart *FCView, mp FCPoint, x1 float64, y1 float64, x2 float64, y2 float64)(bool){
    inChart := chart.GetChart()
    LineXY(chart, x1, y1, x2, y2, 0, 0)
	if !(inChart.KChart == 0 && inChart.BChart == 0) {
        if mp.Y / (mp.X * inChart.KChart + inChart.BChart) >= 0.9 && mp.Y / (mp.X * inChart.KChart + inChart.BChart) <= 1.1 {
            return true
        }
    } else {
        if mp.X >= x1 - inChart.PlotPointSizeChart && mp.X <= x1 + inChart.PlotPointSizeChart {
            return true
        }
    }
    return false
}

/*
* 判断是否选中射线
* mp:坐标
* x1:横坐标1
* y1:纵坐标1
* x2:横坐标2
* y2:纵坐标2
*/
func SelectRay(chart *FCView, mp FCPoint, x1 float64, y1 float64, x2 float64, y2 float64)(bool){
    LineXY(chart, x1, y1, x2, y2, 0, 0)
    inChart := chart.GetChart()
    if !(inChart.KChart == 0 && inChart.BChart == 0) {
        if mp.Y / (mp.X * inChart.KChart + inChart.BChart) >= 0.9 && mp.Y / (mp.X * inChart.KChart + inChart.BChart) <= 1.1 {
            if x1 >= x2 {
                if mp.X > x1 + inChart.PlotPointSizeChart {
                    return false
                }
            } else if x1 < x2 {
                if mp.X < x1 - inChart.PlotPointSizeChart{
                    return false
                }
            }
            return true
        }
    } else {
        if mp.X >= x1 - inChart.PlotPointSizeChart && mp.X <= x1 + inChart.PlotPointSizeChart {
            if y1 >= y2 {
                if mp.Y <= y1 - inChart.PlotPointSizeChart {
                    return true
                }
            } else {
                if mp.Y >= y1 - inChart.PlotPointSizeChart {
                    return true
                }
            }
        }
    }
    return false
}

/*
* 判断是否选中线段
* mp:坐标
* x1:横坐标1
* y1:纵坐标1
* x2:横坐标2
* y2:纵坐标2
*/
func SelectSegment(chart *FCView, mp FCPoint, x1 float64, y1 float64, x2 float64, y2 float64)(bool){
    LineXY(chart, x1, y1, x2, y2, 0, 0)
    smallX := 0.0
    smallY := 0.0
    bigX := 0.0
    bigY := 0.0
    if x1 <= x2{
        smallX = x1
    }else{
        smallX = x2
    }
    if y1 <= y2{
        smallY = y1
    }else{
        smallY = y2
    }
    if x1 > x2{
        bigX = x1
    }else{
        bigX = x2
    }
    if y1 > y2{
        bigY = y1
    }else{
        bigY = y2
    }
    inChart := chart.GetChart()
    if mp.X >= smallX - 2 && mp.X <= bigX + 2 && mp.Y >= smallY - 2 && mp.Y <= bigY + 2 {
        if (inChart.KChart != 0 || inChart.BChart != 0) {
            if mp.Y / (mp.X * inChart.KChart + inChart.BChart) >= 0.9 && mp.Y / (mp.X * inChart.KChart + inChart.BChart) <= 1.1 {
                return true
            }
        } else {
            if mp.X >= x1 - inChart.PlotPointSizeChart && mp.X <= x1 + inChart.PlotPointSizeChart {
                return true
            }
        }
    }
    return false
}

/*
* 根据三点计算圆心
* x1:横坐标1
* y1:纵坐标1
* x2:横坐标2
* y2:纵坐标2
* x3:横坐标3
* y3:纵坐标3
*/
func EllipseOR(chart *FCView, x1 float64, y1 float64, x2 float64, y2 float64, x3 float64, y3 float64) {
    inChart := chart.GetChart()
    inChart.OXChart = ((y3 - y1) * (y2 * y2 - y1 * y1 + x2 * x2 - x1 * x1) + (y2 - y1) * (y1 * y1 - y3 * y3 + x1 * x1 - x3 * x3)) / (2.0 * (x2 - x1) * (y3 - y1) - 2.0 * (x3 - x1) * (y2 - y1))
    inChart.OYChart = ((x3 - x1) * (x2 * x2 - x1 * x1 + y2 * y2 - y1 * y1) + (x2 - x1) * (x1 * x1 - x3 * x3 + y1 * y1 - y3 * y3)) / (2.0 * (y2 - y1) * (x3 - x1) - 2.0 * (y3 - y1) * (x2 - x1))
	inChart.RChart = math.Sqrt(float64((x1 - inChart.OXChart) * (x1 - inChart.OXChart) + (y1 - inChart.OYChart) * (y1 - inChart.OYChart)))
}

/*
* 判断点是否在椭圆上
* x:横坐标
* y:纵坐标
* oX:坐标起始X
* oY:坐标起始Y
* a:椭圆参数a
* b:椭圆参数b
*/
func EllipseHasPoint(ix float64, iy float64, oX float64, oY float64,  a float64, b float64)(bool){
    newX := ix
	newY := iy
	newX = ix - oX
    newY = iy - oY
    if a == 0.0 && b == 0.0 && newX == 0.0 && newY == 0.0 {
        return true
    }
    if a == 0.0 {
        if newX == 0.0 && newY >= -b && newY <= b {
            return false
        }
    }
    if b == 0.0 {
        if iy == 0.0 && newX >= -a && newX <= a {
            return true
        }
    }
    if (newX * newX) / (a * a) + (newY * newY) / (b * b) >= 0.8 && (newX * newX) / (a * a) + (newY * newY) / (b * b) <= 1.2 {
        return true
    }
    return false
}

/*
* 计算线性回归
* list:集合
*/
func LinearRegressionEquation(chart *FCView, list []float64){
    sumX := 0.0
    sumY := 0.0
    sumUp := 0.0
    sumDown := 0.0
    xAvg := 0.0
    yAvg := 0.0
    inChart := chart.GetChart()
    inChart.KChart = 0
    inChart.BChart = 0
    length := len(list)
    if length > 1{
		for i := 0; i < length; i++ {
			sumX = sumX + float64(i) + 1.0
            sumY = sumY + list[i]
		}
        xAvg = sumX / float64(length)
        yAvg = sumY / float64(length)
		for i := 0; i < length; i++ {
			sumUp = sumUp + (float64(i) + 1.0 - xAvg) * (list[i] - yAvg)
            sumDown = sumDown + (float64(i) + 1.0 - xAvg) * (float64(i) + 1.0 - xAvg)
		}
        inChart.KChart = sumUp / sumDown
        inChart.BChart = yAvg - inChart.KChart * xAvg
    }
}

/*
* 计算最大值
* list:集合
*/
func MaxValue(list []float64)(float64){
    length := len(list)
	max := 0.0
	if length > 0{
		max = list[0]
	}
	for i := 0; i < length; i++ {
		if max < list[i]{
			max = list[i]
		}
	}
	return max
}

/*
* 计算最小值
* list:集合
*/
func MinValue(list []float64)(float64){
    length := len(list)
	min := 0.0
	if length > 0{
		min = list[0]
	}
	for i := 0; i < length; i++ {
		if min > list[i]{
			min = list[i]
		}
	}
	return min
}

/*
* 计算平均值
* list:集合
*/
func AvgValue(list []float64)(float64){
    length := len(list)
	sum := 0.0
	for i := 0; i < length; i++ {
		sum = sum + list[i]
	}
	sum = sum / float64(length)
	return sum
}

/*
* 计算平行四边形参数
* x1:横坐标1
* y1:纵坐标1
* x2:横坐标2
* y2:纵坐标2
* x3:横坐标3
* y3:纵坐标3
*/
func Parallelogram(chart *FCView, x1 float64, y1 float64, x2 float64, y2 float64, x3 float64, y3 float64) {
    inChart := chart.GetChart()
    inChart.X4Chart = x1 + x3 - x2
    inChart.Y4Chart = y1 + y3 - y2
}

/*
* 获取图表的区域
* chart: 图表
* plot: 画线
*/
func GetCandleRange(chart *FCView, plot *FCPlot) {
    inChart := chart.GetChart()
    bIndex := GetChartIndexByDate(chart, plot.Key1)
    eIndex := GetChartIndexByDate(chart, plot.Key2)
    tempBIndex := int(math.Min(float64(bIndex), float64(eIndex)))
    tempEIndex := int(math.Max(float64(bIndex), float64(eIndex)))
    bIndex = tempBIndex
    eIndex = tempEIndex
    var highList []float64
    var lowList []float64
    for i := bIndex; i <= eIndex; i++ {
        highList = append(highList, inChart.Data[i].High)
        lowList = append(lowList, inChart.Data[i].Low)
    }
    inChart.NHighChart = MaxValue(highList)
    inChart.NLowChart = MinValue(lowList)
}

/*
* 获取百分比线的刻度
* y1: 纵坐标1
* y2: 纵坐标2
*/
func GetPercentParams(y1 float64, y2 float64)([]float64) {
    var list []float64
    y0 := 0.0
    y25 := 0.0
    y50 := 0.0
    y75 := 0.0
    y100 := 0.0
    y0 = y1
    if y1 <= y2{
        y25 = y1 + (y2 - y1) / 4
        y50 = y1 + (y2 - y1) / 2
        y75 = y1 + (y2 - y1) * 3 / 4
    }else{
        y25 = y2 + (y1 - y2) * 3 / 4
        y50 = y2 + (y1 - y2) / 2
        y75 = y2 + (y1 - y2) / 4
    }
    y100 = y2
    list = append(list, y0)
    list = append(list, y25)
    list = append(list, y50)
    list = append(list, y75)
    list = append(list, y100)
    return list
}

/*
* 计算斐波那契数列
* index:索引
*/
func FibonacciValue(index int)(int) {
    if index < 1{
        return 0
    }
	var vList []int
	for i := 0; i < index; i++ {
		vList = append(vList, 0)
	}
	result := 0
	for i := 0; i < index; i++ {
		if i == 0 || i == 1{
			vList[i] = 1
		}else{
			vList[i] = vList[i - 1] + vList[i - 2]
		}
	}
	result = vList[index - 1]
	return result
}

/*
* 根据坐标计算矩形
* x1:横坐标1
* y1:纵坐标1
* x2:横坐标2
* y2:纵坐标2
*/
func RectangleXYWH(chart *FCView, x1 float64, y1 float64, x2 float64, y2 float64) {
    inChart := chart.GetChart()
    if x1 < x2{
		inChart.XChart = x1
	}else{
		inChart.XChart = x2
	}
	if y1 < y2{
		inChart.YChart = y1
	}else{
		inChart.YChart = y2
	}
    inChart.WChart = math.Abs(float64(x1 - x2))
    inChart.HChart = math.Abs(float64(y1 - y2))
    if inChart.WChart <= 0.0 {
        inChart.WChart = 4.0
    }
    if inChart.HChart <= 0.0 {
        inChart.HChart = 4.0
    }
}

/*
 * 计算最大值
 * @param {Object} ticks 最高价数组
 * @param {Object} days
 */
func HHVValue(ticks []float64, days int)([]float64) {
    var hhv []float64
	max := ticks[0];
	length := len(ticks)
    for i := 0; i < length; i++ {
		max = 0.0
		if i >= days{
			max = ticks[i]
            j := i
            for{
				if j > i - days{
                    if max < ticks[j] {
					    max = ticks[j]
				    }
				}else{
                    break
                }
                j = j - 1
            }
			hhv = append(hhv, max)
		} else {
			if max < ticks[i] {
				max = ticks[i]
			}
			hhv = append(hhv, max)
		}
	}
	return hhv
}

/*
 * 计算最小值
 * @param {Object} ticks 最低价数组
 * @param {Object} days
 */
func LLVValue(ticks []float64, days int)([]float64) {
    var llv []float64
	min := ticks[0];
	length := len(ticks)
    for i := 0; i < length; i++ {
		min = 0.0
		if i >= days {
			min = ticks[i]
            j := i
            for{
				if j > i - days{
                    if min > ticks[j] {
					    min = ticks[j]
				    }
				}else{
                    break
                }
                
                j = j - 1
            }
			llv = append(llv, min)
		} else {
			if min > ticks[i] {
				min = ticks[i]
			}
			llv = append(llv, min)
		}
	}
	return llv
}

/*
* REF函数
* ticks:数据
* days:日数
*/
func RefValue(ticks []float64, days int)([]float64) {
    var refArr []float64
	length := len(ticks)
    for i := 0; i < length; i++ {
		RefValue := 0.0
		if i >= days {
			RefValue = ticks[i - days]
		} else {
			RefValue = ticks[0];
		}
		refArr = append(refArr, RefValue)
	}
	return refArr
}

/*
* 获取TRIX的数据
* ticks:数据
*/
func GetTRIXData(chart *FCView, n int, m int, ticks []float64){
    inChart := chart.GetChart()
    length := len(ticks)
    var mtrArr []float64
    var emaArr1 []float64
    emaArr1 = append(emaArr1, ticks[0])
    for i := 1; i < length; i++ {
        emaArr1 = append(emaArr1, GetEMA(n, ticks[i], emaArr1[i - 1]))
    }
    var emaArr2 []float64
    emaArr2 = append(emaArr2, emaArr1[0])
    for i := 1; i < length; i++ {
        emaArr2 = append(emaArr2, GetEMA(n, emaArr1[i], emaArr2[i - 1]))
    }
    mtrArr = append(mtrArr, emaArr2[0])
    for i := 1; i < length; i++ {
        mtrArr = append(mtrArr, GetEMA(n, emaArr2[i], mtrArr[i - 1]))
    }
    ref := RefValue(mtrArr, 1)
    for i := 0; i < length; i++ {
        trix := 100.0 * (mtrArr[i] - ref[i]) / ref[i]
        inChart.Trix = append(inChart.Trix, trix)
    }
    matrixArrCopy := MaValue(inChart.Trix, m)
    for i := 0; i < len(matrixArrCopy); i++ {
        inChart.TrixMa = append(inChart.TrixMa, matrixArrCopy[i])
    }
}

/*
* 获取方差数据
*/
func StandardDeviationSum(listValue []float64, AvgValue float64)(float64){
    targetValue := listValue[len(listValue) - 1]
    sumValue := (targetValue - AvgValue) * (targetValue - AvgValue)
    for i := 0; i < len(listValue) - 1; i++ {
        ileft := listValue[i]
        sumValue = sumValue + (ileft - AvgValue) * (ileft - AvgValue)
    }
    return sumValue
}

/*
 * 计算boll指标,ma的周期为20日
 *
 * @method BOLL
 * @param {Array} ticks
 * 一维数组类型，每个元素为当前Tick的收盘价格
 * @return {Object} 返回一个包含upper mid lower属性的对象,每个属性对应的类型为{Array[Number]}
 */
func GetBollData(chart *FCView, maDays int, ticks []float64){
    inChart := chart.GetChart()
	tickBegin := maDays - 1
	maSum := 0.0
	p := 0.0
    length := len(ticks)
	for i := 0; i < length; i++ {
		c := ticks[i]
        ma := 0.0
        md := 0.0
        bstart :=  0
        mdSum := 0.0
		maSum = maSum + c;
        if i >= tickBegin {
			maSum = maSum - p;
			ma = maSum / float64(maDays)
			bstart = i - tickBegin
			p = ticks[bstart];
			inChart.BollMid = append(inChart.BollMid, ma)
			bstart = i - tickBegin
			p = ticks[bstart];
            var values []float64
            for j := bstart; j < bstart + maDays; j++ {
                values = append(values, ticks[j])
            }
            mdSum = StandardDeviationSum(values, ma)
			md = math.Sqrt(mdSum / float64(maDays))
			inChart.BollUp = append(inChart.BollUp, ma + 2.0 * md)
			inChart.BollDown = append(inChart.BollDown, ma - 2.0 * md)
		} else {
			ma = maSum / float64(i + 1)
			inChart.BollMid = append(inChart.BollMid, ma)
			var values []float64
            for j := bstart; j < bstart + maDays; j++ {
                values = append(values, ticks[j])
            }
            mdSum = StandardDeviationSum(values, ma)
			md = math.Sqrt(mdSum / float64(i + 1))
			inChart.BollUp = append(inChart.BollUp, ma + 2.0 * md)
			inChart.BollDown = append(inChart.BollDown, ma - 2.0 * md)
		}
	}
}

/*
 *
 * 计算kdj指标,rsv的周期为9日
 *
 * @method KDJ
 * @param {Array} ticks
 * 二维数组类型，其中内层数组包含三个元素值，第一个值表示当前Tick的最高价格，第二个表示当前Tick的最低价格，第三个表示当前Tick的收盘价格
 * @return {Object} 返回一个包含k d j属性的对象,每个属性对应的类型为{Array[Number]}
 */
func GetKDJData(chart *FCView, highArr []float64, lowArr []float64, closeArr []float64, n int, m1 int, m2 int) {
    inChart := chart.GetChart()
    days := n
	var rsvs []float64
    lastK := 0.0
    lastD := 0.0
    curK := 0.0
    curD :=0.0
    length := len(highArr)
	for i := 0; i < length; i++ {
		var highList []float64
		var lowList []float64
        startIndex := i - days
        if startIndex < 0{
            startIndex = 0
        }
		for j := startIndex; j <= i; j++ {
            highList = append(highList, highArr[j])
            lowList = append(highList, lowArr[j])
        }
        close := closeArr[i]
        maxHigh := 0.0
        minLow := 0.0
        for m := 0; m < len(highList); m++ {
            high := highList[m]
            low := lowList[m]
            if high > maxHigh{
                maxHigh = high
            }
            if low < minLow{
                minLow = low
            }
        }
        if maxHigh == minLow {
			rsvs = append(rsvs, 0.0)
		} else {
			rsvs = append(rsvs, (close - minLow) / (maxHigh - minLow) * 100.0)
		}
		if i == 0 {
			lastK = rsvs[i]
            lastD = rsvs[i]
		}
		curK = float64(m1 - 1.0) / float64(m1) * lastK + 1.0 / float64(m1) * rsvs[i]
		inChart.KdjK = append(inChart.KdjK, curK)
		lastK = curK

		curD = float64(m2 - 1.0) / float64(m2) * lastD + 1.0 / float64(m2) * curK
		inChart.KdjD = append(inChart.KdjD, curD)
		lastD = curD

		inChart.KdjJ = append(inChart.KdjJ, 3.0 * curK - 2.0 * curD)
    }
}

/*
 *
 * 计算rsi指标,分别返回以6日，12日，24日为参考基期的RSI值
 *
 * @method RSI
 * @param {Array} ticks
 * 一维数组类型，每个元素为当前Tick的收盘价格
 * @return {Object} 返回一个包含rsi6 rsi12 rsi24属性的对象,每个属性对应的类型为{Array[Number]}
 */
func GetRSIData(chart *FCView, n1 int, n2 int, n3 int, ticks []float64) {
    inChart := chart.GetChart()
    lastClosePx := ticks[0]
    lastSm1 :=  0.0
    lastSa1 := 0.0
    lastSm2 := 0.0
    lastSa2 := 0.0
    lastSm3 := 0.0
    lastSa3 := 0.0
    length := len(ticks)
	for i := 0; i < length; i++ {
        c := ticks[i];
		m := math.Max(c - lastClosePx, 0.0)
		a := math.Abs(c - lastClosePx)
        if i == 0{
            lastSm1 = 0.0
            lastSa1 = 0.0
            inChart.Rsi1 = append(inChart.Rsi1, 0.0)
        }else{
            lastSm1 = (m + (float64(n1 - 1)) * lastSm1) / float64(n1)
		    lastSa1 = (a + (float64(n1 - 1)) * lastSa1)/ float64(n1)
            if lastSa1 != 0.0 {
                inChart.Rsi1 = append(inChart.Rsi1, lastSm1 / lastSa1 * 100.0)
			} else {
				inChart.Rsi1 = append(inChart.Rsi1, 0.0)
			}
        }

         if i == 0{
            lastSm2 = 0.0
            lastSa2 = 0.0
            inChart.Rsi2 = append(inChart.Rsi2, 0.0)
        }else{
            lastSm2 = (m + (float64(n2 - 1)) * lastSm2) / float64(n2)
		    lastSa2 = (a + (float64(n2 - 1)) * lastSa2)/ float64(n2)
            if lastSa2 != 0.0 {
                inChart.Rsi2 = append(inChart.Rsi2, lastSm2 / lastSa2 * 100.0)
			} else {
				inChart.Rsi2 = append(inChart.Rsi2, 0.0)
			}
        }

         if i == 0{
            lastSm3 = 0.0
            lastSa3 = 0.0
            inChart.Rsi3 = append(inChart.Rsi3, 0.0)
        }else{
            lastSm3 = (m + (float64(n3 - 1)) * lastSm3) / float64(n3)
		    lastSa3 = (a + (float64(n3 - 1)) * lastSa3)/ float64(n3)
            if lastSa3 != 0.0 {
                inChart.Rsi3 = append(inChart.Rsi3, lastSm3 / lastSa3 * 100.0)
			} else {
				inChart.Rsi3 = append(inChart.Rsi3, 0.0)
			}
        }
        lastClosePx = c;
    }
}

/*
 * MA数据计算
 * @param {Object} ticks 收盘价数组
 * @param {Object} days 天数
 */
func MaValue(ticks []float64, days int)([]float64) {
    maSum := 0.0
	var mas []float64
	last := 0.0
	length := len(ticks)
	for i := 0; i < length; i++ {
		ma := 0.0
		if i >= days {
			last = ticks[i - days]
			maSum = maSum + ticks[i] - last
			ma = maSum / float64(days)
		} else {
			maSum = maSum + ticks[i]
			ma = maSum / float64(i + 1)
		}
		mas = append(mas, ma)
	}
	return mas
}

/*
 * 计算ROC数据
 * @param {Object} ticks 收盘价数组
 */
func GetRocData(chart *FCView, n int, m int, ticks []float64) {
    inChart := chart.GetChart()
	length := len(ticks)
	for i := 0; i < length; i++ {
		currRoc := 0.0
		if i >= n {
			currRoc = 100.0 * (ticks[i] - ticks[i - n]) / ticks[i - n]
			inChart.Roc = append(inChart.Roc, currRoc)
		} else {
			currRoc = 100.0 * (ticks[i] - ticks[0]) / ticks[0]
			inChart.Roc = append(inChart.Roc, currRoc)
		}
	}
	maResult := MaValue(inChart.Roc, m)
	length = len(maResult)
    for i := 0; i < length; i++ {
        inChart.RocMa = append(inChart.RocMa, maResult[i])
    }
}

/*
 * 获取BIAS的数据
 * @param {Array} ticks 收盘价数组
 * @return
 */
func GetBIASData(chart *FCView, n1 int, n2 int, n3 int, ticks []float64) {
    inChart := chart.GetChart()
    ma1 := MaValue(ticks, n1)
	ma2 := MaValue(ticks, n2)
	ma3 := MaValue(ticks, n3)
	length := len(ticks)
	for i := 0; i < length; i++ {
		b1 := (ticks[i] - ma1[i]) / ma1[i] * 100.0
		b2 := (ticks[i] - ma2[i]) / ma2[i] * 100.0
		b3 := (ticks[i] - ma3[i]) / ma3[i] * 100.0
		inChart.Bias1 = append(inChart.Bias1, b1)
		inChart.Bias2 = append(inChart.Bias2, b2)
		inChart.Bias3 = append(inChart.Bias3, b3)
	}
}

/*
 * 计算BBI(多空指标)
 * @param {Object} ticks
 */
func GetBBIData(chart *FCView, ticks []float64, n1 int, n2 int, n3 int, n4 int) {
    inChart := chart.GetChart()
    ma3 := MaValue(ticks, n1)
	ma6 := MaValue(ticks, n2)
	ma12 := MaValue(ticks, n3)
	ma24 := MaValue(ticks, n4)
	length := len(ticks)
	for i := 0; i < length; i++ {
		bbi := (ma3[i] + ma6[i] + ma12[i] + ma24[i]) / 4.0
		inChart.Bbi = append(inChart.Bbi, bbi)
	}
}

/*
 * 计算WR(威廉指标)
 * @param {Array} ticks 含最高价,最低价, 收盘价的二维数组
 * @param {Object} days
 */
func GetWRData(chart *FCView, highArr []float64, lowArr []float64, closeArr []float64, n1 int, n2 int){
    inChart := chart.GetChart()
	highArr1 := HHVValue(highArr, n1)
	highArr2 := HHVValue(highArr, n2)
	lowArr1 := LLVValue(lowArr, n1)
	lowArr2 := LLVValue(lowArr, n2)
	length := len(highArr)
	for i := 0; i < length; i++ {
		high1 := highArr1[i]
		low1 := lowArr1[i]
		high2 := highArr2[i]
		low2 := lowArr2[i]
		close := closeArr[i]
		wr1 := 100.0 * (high1 - close) / (high1 - low1)
		wr2 := 100.0 * (high2 - close) / (high2 - low2)
		inChart.Wr1 = append(inChart.Wr1, wr1)
		inChart.Wr2 = append(inChart.Wr2, wr2)
	}
}

/*
 * 计算DMA（平均差）
 * @param {Object} ticks 收盘价数组
 */
func GetDMAData(chart *FCView, n1 int, n2 int, ticks []float64) {
    inChart := chart.GetChart()
	ma10 := MaValue(ticks, n1)
	ma50 := MaValue(ticks, n2)
	length := len(ticks)
	for i := 0; i < length; i++ {
		dif := ma10[i] - ma50[i]
		inChart.Dma1 = append(inChart.Dma1, dif)
	}
    maResult := MaValue(inChart.Dma1, n1)
	length = len(maResult)
    for i := 0; i < length; i++ {
        inChart.Dma2 = append(inChart.Dma2, maResult[i])
    }
}

/*
 * CCI(顺势指标)计算  CCI（N日）=（TP－MA）÷MD÷0.015
 * @param {Object} ticks 带最高价，最低价，收盘价的二维数组
 */
func GetCCIData(chart *FCView, highArr []float64, lowArr []float64, n int, closeArr []float64) {
    inChart := chart.GetChart()
	var tpArr []float64
	length := len(closeArr)
	for i := 0; i < length; i++ {
		tpArr = append(tpArr, (highArr[i] + lowArr[i] + closeArr[i]) / 3.0)
	}
	maClose := MaValue(closeArr, n)
	var mdArr []float64
	for i := 0; i < length; i++ {
		mdArr = append(mdArr, maClose[i] - closeArr[i])
	}
	maMD := MaValue(mdArr, n)
	for i := 0; i < length; i++ {
		cci := (tpArr[i] - maClose[i]) / (maMD[i] * 0.015)
		inChart.Cci = append(inChart.Cci, cci)
	}
}

/*
* 图表的鼠标按下方法
* chart: 图表
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
*/
func TouchDownChart(chart *FCView, firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint) {
    inChart := chart.GetChart()
    inChart.TouchDownPointChart = CreatePoint(firstPoint.X, firstPoint.Y)
    inChart.CrossStopIndex = GetChartIndex(chart, firstPoint)
	inChart.TargetOldX = 0
	inChart.TargetOldX2 = 0
    inChart.SelectShape = ""
    inChart.SelectShapeEx = ""
    var pList []*FCPlot
    inChart.SPlot = pList
    if len(inChart.Data) > 0 {
        selectedPlot := SelectPlot(chart, firstPoint)
        if selectedPlot.IsNotEmpty{
            inChart.SetSelectedPlot(selectedPlot)
        }
        if !inChart.GetSelectedPlot().IsNotEmpty {
            SelectShape(chart, firstPoint)
        }
    }
    if chart.GetPaint().IsDoubleClick{
		inChart.ShowCrossLine = !inChart.ShowCrossLine
	}
}

/*
*左滚
*chart:图表
*step:步长
*/
func ScrollLeftChart(chart *FCView, step int){
    inChart := chart.GetChart()
	inChart.TargetOldX = 0
	inChart.TargetOldX2 = 0
	if inChart.ShowCrossLine{
		inChart.CrossStopIndex = inChart.CrossStopIndex - step
		if inChart.CrossStopIndex >= inChart.FirstVisibleIndex{
			step = 0
		}else if inChart.CrossStopIndex < 0{
			inChart.CrossStopIndex = 0
		}
	}
	if step > 0{
		subIndex := inChart.LastVisibleIndex - inChart.FirstVisibleIndex
		fIndex := inChart.FirstVisibleIndex - step
		if fIndex < 0{
			fIndex = 0
		}
		eIndex := fIndex + subIndex
		inChart.FirstVisibleIndex = fIndex
		inChart.LastVisibleIndex = eIndex
	}
	CheckChartLastVisibleIndex(chart)
	if inChart.OnCalculateChartMaxMin != nil{
        inChart.OnCalculateChartMaxMin(chart)
    }else if chart.GetPaint().OnCalculateChartMaxMin != nil{
        chart.GetPaint().OnCalculateChartMaxMin(chart)
    }else{
        CalculateChartMaxMin(chart)
    }
}

/*
*右滚
*chart:图表
*step:步长
*/
func ScrollRightChart(chart *FCView, step int){
    inChart := chart.GetChart()
	inChart.TargetOldX = 0
	inChart.TargetOldX2 = 0
	dataCount := len(inChart.Data)
	if inChart.ShowCrossLine{
		inChart.CrossStopIndex = inChart.CrossStopIndex + step
		if inChart.CrossStopIndex <= inChart.LastVisibleIndex{
			step = 0
		}else if inChart.CrossStopIndex > dataCount - 1{
			inChart.CrossStopIndex = dataCount - 1
		}
	}
	if step > 0{
		subIndex := inChart.LastVisibleIndex - inChart.FirstVisibleIndex
		eIndex := inChart.LastVisibleIndex + step
		if eIndex > dataCount - 1{
			eIndex = dataCount - 1
		}
		fIndex := eIndex - subIndex
		inChart.FirstVisibleIndex = fIndex
		inChart.LastVisibleIndex = eIndex
	}
	CheckChartLastVisibleIndex(chart)
	if inChart.OnCalculateChartMaxMin != nil{
        inChart.OnCalculateChartMaxMin(chart)
    }else if chart.GetPaint().OnCalculateChartMaxMin != nil{
        chart.GetPaint().OnCalculateChartMaxMin(chart)
    }else{
        CalculateChartMaxMin(chart)
    }
}

/*
*图表的键盘按下事件
*chart:图表
*key:按键
*/
func keyDownChart(chart *FCView, key int){
	if (key == 38){
		ZoomOutChart(chart)
	}else if(key == 40){
		ZoomInChart(chart)
	}else if(key == 37){
		ScrollLeftChart(chart, 1)
	}else if(key == 39){
		ScrollRightChart(chart, 1)
	}
}

/*
* 添加画线
* chart: 图表
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
*/
func AddPlotDefault(chart *FCView, firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint) {
    inChart := chart.GetChart()
    mp := CreatePoint(firstPoint.X, firstPoint.Y)
    if mp.Y < GetCandleDivHeight(chart) {
        touchIndex := GetChartIndex(chart, mp)
        if touchIndex >= inChart.FirstVisibleIndex && touchIndex <= inChart.LastVisibleIndex {
            if inChart.AddingPlotChart == "FiboTimezone" {
                fIndex := touchIndex
                fDate := GetChartDateByIndex(chart, fIndex)
                y := GetChartValue(chart, mp)
                newPlot := CreatePlot()
                if chart.GetPaint().DefaultUIStyle == "light" {
                    newPlot.LineColor = "rgb(0,0,0)"
                    newPlot.PointColor = "rgba(0,0,0,125)"
                } else {
                    newPlot.LineColor = "rgb(255,255,255)"
                    newPlot.PointColor = "rgba(255,255,255,125)"
                }
                newPlot.Key1 = fDate
                newPlot.Value1 = y
                newPlot.PlotType = inChart.AddingPlotChart
                inChart.Plots = append(inChart.Plots, newPlot)
                var pList []*FCPlot
                inChart.SPlot = pList
                selectedPlot := SelectPlot(chart, mp)
                if selectedPlot.IsNotEmpty{
                    inChart.SetSelectedPlot(selectedPlot)
                }
            }else if inChart.AddingPlotChart == "Triangle" || inChart.AddingPlotChart == "CircumCycle" || inChart.AddingPlotChart == "ParalleGram" || inChart.AddingPlotChart == "AngleLine" || inChart.AddingPlotChart == "Parallel" || inChart.AddingPlotChart == "SymmetricTriangle" {
                eIndex := touchIndex
                bIndex := eIndex - 5
                if bIndex >= 0 {
                    fDate := GetChartDateByIndex(chart, bIndex)
                    sDate := GetChartDateByIndex(chart, eIndex)
                    y := GetChartValue(chart, mp)
                    newPlot := CreatePlot()
                    if chart.GetPaint().DefaultUIStyle == "light" {
                        newPlot.LineColor = "rgb(0,0,0)"
                        newPlot.PointColor = "rgba(0,0,0,125)"
                    } else {
                        newPlot.LineColor = "rgb(255,255,255)"
                        newPlot.PointColor = "rgba(255,255,255,125)"
                    }
                    newPlot.Key1 = fDate
                    newPlot.Value1 = y
                    newPlot.Key2 = sDate
                    newPlot.Value2 = y
                    newPlot.Key3 = sDate
                    newPlot.Value3 = inChart.CandleMin + (inChart.CandleMax - inChart.CandleMin) / 2
                    newPlot.PlotType = inChart.AddingPlotChart
                    inChart.Plots = append(inChart.Plots, newPlot)
                    var pList []*FCPlot
                    inChart.SPlot = pList
                    selectedPlot := SelectPlot(chart, mp)
                    if selectedPlot.IsNotEmpty{
                        inChart.SetSelectedPlot(selectedPlot)
                    }
                }
            } else {
                eIndex := touchIndex
                bIndex := eIndex - 5
                if bIndex >= 0 {
                    fDate := GetChartDateByIndex(chart, bIndex)
                    sDate := GetChartDateByIndex(chart, eIndex)
                    y := GetChartValue(chart, mp)
                    newPlot := CreatePlot()
                    if chart.GetPaint().DefaultUIStyle == "light"{
                        newPlot.LineColor = "rgb(0,0,0)"
                        newPlot.PointColor = "rgba(0,0,0,125)"
                    } else {
                        newPlot.LineColor = "rgb(255,255,255)"
                        newPlot.PointColor = "rgba(255,255,255,125)"
                    }
                    newPlot.Key1 = fDate
                    newPlot.Value1 = y
                    newPlot.Key2 = sDate
                    newPlot.Value2 = y
                    newPlot.PlotType = inChart.AddingPlotChart
                    inChart.Plots = append(inChart.Plots, newPlot)
                    var pList []*FCPlot
                    inChart.SPlot = pList
                    selectedPlot := SelectPlot(chart, mp)
                    if selectedPlot.IsNotEmpty{
                        inChart.SetSelectedPlot(selectedPlot)
                    }
                }
            }
        }
    }
}

/*
* 图表的鼠标移动方法
* chart: 图表
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
*/
func TouchMoveChart(chart *FCView, firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint) {
    inChart := chart.GetChart()
    if len(inChart.Data) == 0 {
        return
    }
    mp := CreatePoint(firstPoint.X, firstPoint.Y)
    inChart.CrossStopIndex = GetChartIndex(chart, mp)
    inChart.TouchPosition = mp
	inChart.TargetOldX = 0
	inChart.TargetOldX2 = 0
    sPlot := inChart.GetSelectedPlot()
    if firstTouch && sPlot.IsNotEmpty {
        newIndex := GetChartIndex(chart, mp)
        if newIndex >= 0 && newIndex < len(inChart.Data) {
            newDate := GetChartDateByIndex(chart, newIndex)
            newValue := GetCandleDivValue(chart, mp)
            if inChart.SelectPlotPoint == 0 {
                sPlot.Key1 = newDate
                sPlot.Value1 = newValue
            } else if inChart.SelectPlotPoint == 1 {
                sPlot.Key2 = newDate
                sPlot.Value2 = newValue
            } else if inChart.SelectPlotPoint == 2 {
                sPlot.Key3 = newDate
                sPlot.Value3 = newValue
            }else if inChart.StartMovePlot {
                bValue := GetCandleDivValue(chart, inChart.TouchDownPointChart)
                bIndex := GetChartIndex(chart, inChart.TouchDownPointChart)
                if sPlot.Key1 > 0 {
                    sPlot.Value1 = sPlot.StartValue1 + (newValue - bValue)
                    startIndex1 := GetChartIndexByDate(chart, sPlot.StartKey1)
                    newIndex1 := startIndex1 + (newIndex - bIndex)
                    if newIndex1 < 0 {
                        newIndex1 = 0
                    }else if newIndex1 > len(inChart.Data) - 1 {
                        newIndex1 = len(inChart.Data) - 1
                    }
                    sPlot.Key1 = GetChartDateByIndex(chart, newIndex1)
                }
                if sPlot.Key2 > 0 {
                    sPlot.Value2 = sPlot.StartValue2 + (newValue - bValue)
                    startIndex2 := GetChartIndexByDate(chart, sPlot.StartKey2)
                    newIndex2 := startIndex2 + (newIndex - bIndex)
                    if newIndex2 < 0 {
                        newIndex2 = 0
                    }else if (newIndex2 > len(inChart.Data) - 1) {
                        newIndex2 = len(inChart.Data) - 1
                    }
                    sPlot.Key2 = GetChartDateByIndex(chart, newIndex2)
                }
                if sPlot.Key3 > 0 {
                    sPlot.Value3 = sPlot.StartValue3 + (newValue - bValue)
                    startIndex3 := GetChartIndexByDate(chart, sPlot.StartKey3)
                    newIndex3 := startIndex3 + (newIndex - bIndex)
                    if newIndex3 < 0 {
                        newIndex3 = 0
                    }else if (newIndex3 > len(inChart.Data) - 1) {
                        newIndex3 = len(inChart.Data) - 1
                    }
                    sPlot.Key3 = GetChartDateByIndex(chart, newIndex3)
                }
            }
        }
        return
    }
    if firstTouch && secondTouch{
        if firstPoint.X > secondPoint.X {
            inChart.FirstTouchPointCacheChart = secondPoint
            inChart.SecondTouchPointCacheChart = firstPoint
        } else {
            inChart.FirstTouchPointCacheChart = firstPoint
            inChart.SecondTouchPointCacheChart = secondPoint
        }
        if inChart.FirstTouchIndexCacheChart == -1 || inChart.SecondTouchIndexCacheChart == -1 {
            inChart.FirstTouchIndexCacheChart = GetChartIndex(chart, inChart.FirstTouchPointCacheChart)
            inChart.SecondTouchIndexCacheChart = GetChartIndex(chart, inChart.SecondTouchPointCacheChart)
            inChart.FirstIndexCacheChart = inChart.FirstVisibleIndex
            inChart.LastIndexCacheChart = inChart.LastVisibleIndex
        }
    } else if firstTouch {
        inChart.SecondTouchIndexCacheChart = -1
        if inChart.FirstTouchIndexCacheChart == -1 {
            inChart.FirstTouchPointCacheChart = firstPoint
            inChart.FirstTouchIndexCacheChart = GetChartIndex(chart, inChart.FirstTouchPointCacheChart)
            inChart.FirstIndexCacheChart = inChart.FirstVisibleIndex
            inChart.LastIndexCacheChart = inChart.LastVisibleIndex
            inChart.FirstPaddingTop = inChart.CandlePaddingTop
            inChart.FirtstPaddingBottom = inChart.CandlePaddingBottom
        }
    }
    if firstTouch && secondTouch {
        if inChart.FirstTouchIndexCacheChart != -1 && inChart.SecondTouchIndexCacheChart != -1 {
            fPoint := CreatePoint(firstPoint.X, firstPoint.Y)
            sPoint := CreatePoint(secondPoint.X, secondPoint.Y)
            if firstPoint.X > secondPoint.X {
                fPoint = secondPoint
                sPoint = firstPoint
            }
            subX := math.Abs(sPoint.X - fPoint.X)
            subIndex := int(math.Abs(float64(inChart.SecondTouchIndexCacheChart - inChart.FirstTouchIndexCacheChart)))
            if subX > 0 && subIndex > 0 {
                var newScalePixel = subX / float64(subIndex)
                if newScalePixel >= 3 {
                    intScalePixel := float64(int(newScalePixel))
                    newScalePixel = intScalePixel
                }
                if newScalePixel != inChart.HScalePixel {
                    newFirstIndex := inChart.FirstTouchIndexCacheChart
                    thisX := fPoint.X
                    thisX -= newScalePixel
                    for{
                        if thisX > inChart.LeftVScaleWidth + newScalePixel{
                            newFirstIndex -= 1
                            if newFirstIndex < 0 {
                                newFirstIndex = 0
                                break
                            }
                            thisX -= newScalePixel
                        }else{
                            break
                        }
                    }
                    thisX = sPoint.X
                    newSecondIndex := inChart.SecondTouchIndexCacheChart
                    thisX += newScalePixel
                    for{
                        if thisX < chart.Size.Cx - inChart.RightVScaleWidth - newScalePixel {
                            newSecondIndex += 1
                            if newSecondIndex > len(inChart.Data) - 1 {
                                newSecondIndex = len(inChart.Data) - 1
                                break
                            }
                            thisX += newScalePixel
                        }else{
                            break
                        }                       
                    }
                    SetChartVisibleIndex(chart, newFirstIndex, newSecondIndex)
                    maxVisibleRecord := GetChartMaxVisibleCount(chart, inChart.HScalePixel, GetChartWorkAreaWidth(chart))
                    for{
                        if maxVisibleRecord < inChart.LastVisibleIndex - inChart.FirstVisibleIndex + 1 && inChart.LastVisibleIndex > inChart.FirstVisibleIndex{
                            inChart.LastVisibleIndex -= 1
                        }else{
                            break
                        }
                    }
                    CheckChartLastVisibleIndex(chart)
                    ResetChartVisibleRecord(chart)
                    if inChart.OnCalculateChartMaxMin != nil{
                        inChart.OnCalculateChartMaxMin(chart)
                    }else if chart.GetPaint().OnCalculateChartMaxMin != nil{
                        chart.GetPaint().OnCalculateChartMaxMin(chart)
                    }else{
                        CalculateChartMaxMin(chart)
                    }
                }
            }
        }
    } else if firstTouch {
        if !inChart.AutoFillHScale{
            subIndex := int((inChart.FirstTouchPointCacheChart.X - firstPoint.X) / inChart.HScalePixel)
            if inChart.AllowDragChartDiv {
                inChart.CandlePaddingTop = inChart.FirstPaddingTop - (inChart.FirstTouchPointCacheChart.Y - firstPoint.Y)
                inChart.CandlePaddingBottom = inChart.FirtstPaddingBottom + (inChart.FirstTouchPointCacheChart.Y - firstPoint.Y)
            }
            fIndex := inChart.FirstIndexCacheChart + subIndex
            lIndex := inChart.LastIndexCacheChart + subIndex
            if fIndex > len(inChart.Data) - 1{
                fIndex = len(inChart.Data) - 1
                lIndex = len(inChart.Data) - 1
            }
            inChart.FirstVisibleIndex = fIndex
            inChart.LastVisibleIndex = lIndex
            CheckChartLastVisibleIndex(chart)
            if inChart.OnCalculateChartMaxMin != nil{
                inChart.OnCalculateChartMaxMin(chart)
            }else if chart.GetPaint().OnCalculateChartMaxMin != nil{
                chart.GetPaint().OnCalculateChartMaxMin(chart)
            }else{
                CalculateChartMaxMin(chart)
            }
        }
    }
}

/*
* 选中直线
* chart: 图表
* mp:坐标
*/
func SelectPlot(chart *FCView, mp FCPoint)(*FCPlot) {
    inChart := chart.GetChart()
    sPlot := new(FCPlot)
    sPlot.IsNotEmpty = false
    inChart.StartMovePlot = false
    inChart.SelectPlotPoint = -1
    if len(inChart.Plots) > 0{
        for i := 0; i < len(inChart.Plots); i++ {
            plot := inChart.Plots[i]
            index1 := 0
            index2 := 0
            index3 := 0
            mpx1 := 0.0
            mpy1 := 0.0
            mpx2 := 0.0
            mpy2 := 0.0
            mpx3 := 0.0
            mpy3 := 0.0
            //检查关键点
            if plot.Key1 > 0 {
                index1 = GetChartIndexByDate(chart, plot.Key1)
                mpx1 = GetChartX(chart, index1)
                mpy1 = GetChartY(chart, 0, plot.Value1)
                if mp.X >= mpx1 - inChart.PlotPointSizeChart && mp.X <= mpx1 + inChart.PlotPointSizeChart && mp.Y >= mpy1 - inChart.PlotPointSizeChart && mp.Y <= mpy1 + inChart.PlotPointSizeChart {
                    sPlot = plot
                    inChart.SelectPlotPoint = 0
                    break
                }
            }
            if plot.Key2 > 0 {
                index2 = GetChartIndexByDate(chart, plot.Key2)
                mpx2 = GetChartX(chart, index2)
                mpy2 = GetChartY(chart, 0, plot.Value2)
                if mp.X >= mpx2 - inChart.PlotPointSizeChart && mp.X <= mpx2 + inChart.PlotPointSizeChart && mp.Y >= mpy2 - inChart.PlotPointSizeChart && mp.Y <= mpy2 + inChart.PlotPointSizeChart {
                    sPlot = plot
                    inChart.SelectPlotPoint = 1
                    break
                }
            }
            if plot.Key3 > 0 {
                index3 = GetChartIndexByDate(chart, plot.Key3)
                mpx3 = GetChartX(chart, index3)
                mpy3 = GetChartY(chart, 0, plot.Value3)
                if mp.X >= mpx3 - inChart.PlotPointSizeChart && mp.X <= mpx3 + inChart.PlotPointSizeChart && mp.Y >= mpy3 - inChart.PlotPointSizeChart && mp.Y <= mpy3 + inChart.PlotPointSizeChart {
                    sPlot = plot
                    inChart.SelectPlotPoint = 2
                    break
                }
            }
            //判断其余部分的选中
            if inChart.SelectPlotPoint == -1 {
                if plot.PlotType == "Line" {
                    inChart.StartMovePlot = SelectLine(chart, mp, mpx1, mpy1, mpx2, mpy2)
                }else if plot.PlotType == "ArrowSegment" {
                    inChart.StartMovePlot = SelectSegment(chart, mp, mpx1, mpy1, mpx2, mpy2)
                }else if plot.PlotType == "AngleLine" {
                    inChart.StartMovePlot = SelectLine(chart, mp, mpx1, mpy1, mpx2, mpy2)
                    if !inChart.StartMovePlot {
                        inChart.StartMovePlot = SelectLine(chart, mp, mpx1, mpy1, mpx3, mpy3)
                    }
                }else if plot.PlotType == "Parallel" {
                    inChart.StartMovePlot = SelectLine(chart, mp, mpx1, mpy1, mpx2, mpy2)
                    if !inChart.StartMovePlot {
                        LineXY(chart, mpx1, mpy1, mpx2, mpy2, 0, 0)
                        newB := mpy3 - inChart.KChart * mpx3
                        if mpx2 == mpx1 {
                            if mp.X >= mpx3 - inChart.PlotPointSizeChart && mp.X <= mpx3 + inChart.PlotPointSizeChart {
                                inChart.StartMovePlot = true
                            }
                        } else {
                            newX1 := inChart.LeftVScaleWidth
                            newY1 := newX1 * inChart.KChart + newB
                            newX2 := chart.Size.Cx - inChart.RightVScaleWidth
                            newY2 := newX2 * inChart.KChart + newB
                            inChart.StartMovePlot = SelectLine(chart, mp, newX1, newY1, newX2, newY2)
                        }
                    }
                }else if plot.PlotType == "LRLine" {
                    inChart.StartMovePlot = SelectSegment(chart, mp, mpx1, mpy1, mpx2, mpy2)
                }else if plot.PlotType == "Segment" {
                    inChart.StartMovePlot = SelectSegment(chart, mp, mpx1, mpy1, mpx2, mpy2)
                } else if plot.PlotType == "Ray" {
                    inChart.StartMovePlot = SelectRay(chart, mp, mpx1, mpy1, mpx2, mpy2)
                }else if plot.PlotType == "Triangle" {
                    inChart.StartMovePlot = SelectSegment(chart, mp, mpx1, mpy1, mpx2, mpy2)
                    if !inChart.StartMovePlot {
                        inChart.StartMovePlot = SelectSegment(chart, mp, mpx2, mpy2, mpx3, mpy3)
                    }
                    if !inChart.StartMovePlot {
                        inChart.StartMovePlot = SelectSegment(chart, mp, mpx1, mpy1, mpx3, mpy3)
                    }
                }else if plot.PlotType == "SymmetricTriangle" {
                    if mpx2 != mpx1 {
                        a := (mpy2 - mpy1) / (mpx2 - mpx1)
                        b := mpy1 - a * mpx1
                        c := -a
                        d := mpy3 - c * mpx3
                        leftX := inChart.LeftVScaleWidth
                        leftY := leftX * a + b
                        rightX := chart.Size.Cx - inChart.RightVScaleWidth
                        rightY := rightX * a + b
                        inChart.StartMovePlot = SelectSegment(chart, mp, leftX, leftY, rightX, rightY)
                        if !inChart.StartMovePlot {
                            leftY = leftX * c + d
                            rightY = rightX * c + d
                            inChart.StartMovePlot = SelectSegment(chart, mp, leftX, leftY, rightX, rightY)
                        }
                    } else {
                        divHeight := GetCandleDivHeight(chart)
                        inChart.StartMovePlot = SelectSegment(chart, mp, mpx1, 0, mpx1, divHeight)
                        if !inChart.StartMovePlot {
                            inChart.StartMovePlot = SelectSegment(chart, mp, mpx3, 0, mpx3, divHeight)
                        }
                    }
                }else if plot.PlotType == "Rect" {
                    sX1 := math.Min(mpx1, mpx2)
                    sY1 := math.Min(mpy1, mpy2)
                    sX2 := math.Max(mpx1, mpx2)
                    sY2 := math.Max(mpy1, mpy2)
                    inChart.StartMovePlot = SelectSegment(chart, mp, sX1, sY1, sX2, sY1)
                    if !inChart.StartMovePlot {
                        inChart.StartMovePlot = SelectSegment(chart, mp, sX2, sY1, sX2, sY2)
                    }
                    if !inChart.StartMovePlot {
                        inChart.StartMovePlot = SelectSegment(chart, mp, sX1, sY2, sX2, sY2)
                    }
                    if !inChart.StartMovePlot {
                        inChart.StartMovePlot = SelectSegment(chart, mp, sX1, sY1, sX1, sY2)
                    }
                }else if plot.PlotType == "BoxLine" {
                    sX1 := math.Min(mpx1, mpx2)
                    sY1 := math.Min(mpy1, mpy2)
                    sX2 := math.Max(mpx1, mpx2)
                    sY2 := math.Max(mpy1, mpy2)
                    inChart.StartMovePlot = SelectSegment(chart, mp, sX1, sY1, sX2, sY1)
                    if !inChart.StartMovePlot {
                        inChart.StartMovePlot = SelectSegment(chart, mp, sX2, sY1, sX2, sY2)
                    }
                    if !inChart.StartMovePlot {
                        inChart.StartMovePlot = SelectSegment(chart, mp, sX1, sY2, sX2, sY2)
                    }
                    if !inChart.StartMovePlot {
                        inChart.StartMovePlot = SelectSegment(chart, mp, sX1, sY1, sX1, sY2)
                    }
                }else if plot.PlotType == "TironeLevels" {
                    sX1 := math.Min(mpx1, mpx2)
                    sY1 := math.Min(mpy1, mpy2)
                    sX2 := math.Max(mpx1, mpx2)
                    sY2 := math.Max(mpy1, mpy2)
                    inChart.StartMovePlot = SelectSegment(chart, mp, sX1, sY1, sX2, sY1)
                    if !inChart.StartMovePlot {
                        inChart.StartMovePlot = SelectSegment(chart, mp, sX1, sY2, sX2, sY2)
                    }
                }else if plot.PlotType == "QuadrantLines"{
                    sX1 := math.Min(mpx1, mpx2)
                    sY1 := math.Min(mpy1, mpy2)
                    sX2 := math.Max(mpx1, mpx2)
                    sY2 := math.Max(mpy1, mpy2)
                    inChart.StartMovePlot = SelectSegment(chart, mp, sX1, sY1, sX2, sY1)
                    if !inChart.StartMovePlot {
                        inChart.StartMovePlot = SelectSegment(chart, mp, sX1, sY2, sX2, sY2)
                    }
                }else if plot.PlotType == "GoldenRatio" {
                    sY1 := math.Min(mpy1, mpy2)
                    sY2 := math.Max(mpy1, mpy2)
                    var ranges []float64
                    ranges = append(ranges, 0)
                    ranges = append(ranges, 0.236)
                    ranges = append(ranges, 0.382)
                    ranges = append(ranges, 0.5)
                    ranges = append(ranges, 0.618)
                    ranges = append(ranges, 0.809)
                    ranges = append(ranges, 1)
                    ranges = append(ranges, 1.382)
                    ranges = append(ranges, 1.618)
                    ranges = append(ranges, 2)
                    ranges = append(ranges, 2.382)
                    ranges = append(ranges, 2.618)
                    for j := 0; j < len(ranges); j++ {
                        newY := 0.0
                        if sY1 <= sY2{
                            newY = sY1 + (sY2 - sY1) * ranges[j]
                        }else{
                            newY = sY2 + (sY1 - sY2) * (1 - ranges[j])
                        }
                        inChart.StartMovePlot = SelectSegment(chart, mp, inChart.LeftVScaleWidth, newY, chart.Size.Cx - inChart.RightVScaleWidth, newY)
                        if inChart.StartMovePlot {
                            break
                        }
                    }
                }else if plot.PlotType == "Cycle" {
                    r := math.Sqrt(math.Abs((mpx2 - mpx1) * (mpx2 - mpx1) + (mpy2 - mpy1) * (mpy2 - mpy1)))
                    round := (mp.X - mpx1) * (mp.X - mpx1) + (mp.Y - mpy1) * (mp.Y - mpy1)
                    if round / (r * r) >= 0.9 && round / (r * r) <= 1.1 {
                        inChart.StartMovePlot = true
                    }
                } else if plot.PlotType == "CircumCycle" {
                    EllipseOR(chart, mpx1, mpy1, mpx2, mpy2, mpx3, mpy3)
                    round := (mp.X - inChart.OXChart) * (mp.X - inChart.OXChart) + (mp.Y - inChart.OYChart) * (mp.Y - inChart.OYChart)
                    if round / (inChart.RChart * inChart.RChart) >= 0.9 && round / (inChart.RChart * inChart.RChart) <= 1.1 {
                        inChart.StartMovePlot = true
                    }
                }else if plot.PlotType == "Ellipse" {
                    x1 := 0.0
                    y1 := 0.0
                    x2 := 0.0
                    y2 := 0.0
                    if mpx1 <= mpx2 {
                        x1 = mpx2
                        y1 = mpy2
                        x2 = mpx1
                        y2 = mpy1
                    } else {
                        x1 = mpx1
                        y1 = mpy1
                        x2 = mpx2
                        y2 = mpy2
                    }
                    x := x1 - (x1 - x2)
                    y := 0.0
                    width := (x1 - x2) * 2
                    height := 0.0
                    if y1 >= y2 {
                        height = (y1 - y2) * 2
                    }else {
                        height = (y2 - y1) * 2
                    }
                    y = y2 - height / 2
                    a := width / 2
                    b := height / 2
                    inChart.StartMovePlot = EllipseHasPoint(mp.X, mp.Y, x + (width / 2), y + (height / 2), a, b)
                }else if plot.PlotType == "LRBand" {
                    inChart.StartMovePlot = SelectSegment(chart, mp, mpx1, mpy1, mpx2, mpy2)
                    if !inChart.StartMovePlot {
                        var list []float64
                        minIndex := int(math.Min(float64(index1), float64(index2)))
                        maxIndex := int(math.Max(float64(index1), float64(index2)))
                        for j := minIndex; j <= maxIndex; j++ {
                            list = append(list, inChart.Data[j].Close)
                        }
                        LinearRegressionEquation(chart, list)
                        GetLRBandRange(chart, plot, inChart.KChart, inChart.BChart)
                        mpy1 = GetChartY(chart, 0, plot.Value1 + inChart.UpSubValue)
                        mpy2 = GetChartY(chart, 0, plot.Value2 + inChart.UpSubValue)
                        inChart.StartMovePlot = SelectSegment(chart, mp, mpx1, mpy1, mpx2, mpy2)
                        if !inChart.StartMovePlot {
                            mpy1 = GetChartY(chart, 0, plot.Value1 - inChart.DownSubValue)
                            mpy2 = GetChartY(chart, 0, plot.Value2 - inChart.DownSubValue)
                            inChart.StartMovePlot = SelectSegment(chart, mp, mpx1, mpy1, mpx2, mpy2)
                        }
                    }
                }else if (plot.PlotType == "LRChannel") {
                    LineXY(chart, mpx1, mpy1, mpx2, mpy2, 0, 0)
                    rightX := chart.Size.Cx - inChart.RightVScaleWidth
                    rightY := rightX * inChart.KChart + inChart.BChart
                    inChart.StartMovePlot = SelectSegment(chart, mp, mpx1, mpy1, rightX, rightY)
                    if !inChart.StartMovePlot {
                        var list []float64
                        minIndex := int(math.Min(float64(index1), float64(index2)))
                        maxIndex := int(math.Max(float64(index1), float64(index2)))
                        for j := minIndex; j <= maxIndex; j++ {
                            list = append(list, inChart.Data[j].Close)
                        }
                        LinearRegressionEquation(chart, list)
                        GetLRBandRange(chart, plot, inChart.KChart, inChart.BChart)
                        mpy1 = GetChartY(chart, 0, plot.Value1 + inChart.UpSubValue)
                        mpy2 = GetChartY(chart, 0, plot.Value2 + inChart.UpSubValue)
                        LineXY(chart, mpx1, mpy1, mpx2, mpy2, 0, 0)
                        rightY = rightX * inChart.KChart + inChart.BChart
                        inChart.StartMovePlot = SelectSegment(chart, mp, mpx1, mpy1, rightX, rightY)
                        if !inChart.StartMovePlot {
                            mpy1 = GetChartY(chart, 0, plot.Value1 - inChart.DownSubValue)
                            mpy2 = GetChartY(chart, 0, plot.Value2 - inChart.DownSubValue)
                            LineXY(chart, mpx1, mpy1, mpx2, mpy2, 0, 0)
                            rightY = rightX * inChart.KChart + inChart.BChart
                            inChart.StartMovePlot = SelectSegment(chart, mp, mpx1, mpy1, rightX, rightY)
                        }
                    }
                }else if (plot.PlotType == "ParalleGram") {
                    Parallelogram(chart, mpx1, mpy1, mpx2, mpy2, mpx3, mpy3)
                    inChart.StartMovePlot = SelectSegment(chart, mp, mpx1, mpy1, mpx2, mpy2)
                    if !inChart.StartMovePlot {
                        inChart.StartMovePlot = SelectSegment(chart, mp, mpx2, mpy2, mpx3, mpy3)
                        if !inChart.StartMovePlot {
                            inChart.StartMovePlot = SelectSegment(chart, mp, mpx3, mpy3, inChart.X4Chart, inChart.Y4Chart)
                            if !inChart.StartMovePlot {
                                inChart.StartMovePlot = SelectSegment(chart, mp, inChart.X4Chart, inChart.Y4Chart, mpx1, mpy1)
                            }
                        }
                    }
                }else if (plot.PlotType == "SpeedResist") {
                    inChart.StartMovePlot = SelectSegment(chart, mp, mpx1, mpy1, mpx2, mpy2)
                    if !inChart.StartMovePlot {
                        if (mpx1 != mpx2 && mpy1 != mpy2) {
                            firstP := CreatePoint(mpx2, mpy2 - (mpy2 - mpy1) / 3)
                            secondP := CreatePoint(mpx2, mpy2 - (mpy2 - mpy1) * 2 / 3)
                            startP := CreatePoint(mpx1, mpy1)
                            fK := 0.0
                            fB := 0.0
                            sK := 0.0
                            sB := 0.0
                            LineXY(chart, startP.X, startP.Y, firstP.X, firstP.Y, 0, 0)
                            fK = inChart.KChart
                            fB = inChart.BChart
                            LineXY(chart, startP.X, startP.Y, secondP.X, secondP.Y, 0, 0)
                            sK = inChart.KChart
                            sB = inChart.BChart
                            newYF := 0.0
                            newYS := 0.0
                            newX := 0.0
                            if mpx2 > mpx1 {
                                newYF = fK * (chart.Size.Cx - inChart.RightVScaleWidth) + fB
                                newYS = sK * (chart.Size.Cx - inChart.RightVScaleWidth) + sB
                                newX = (chart.Size.Cx - inChart.RightVScaleWidth)
                            }else {
                                newYF = fB
                                newYS = sB
                                newX = inChart.LeftVScaleWidth
                            }
                            inChart.StartMovePlot = SelectSegment(chart, mp, startP.X, startP.Y, newX, newYF)
                            if !inChart.StartMovePlot {
                                inChart.StartMovePlot = SelectSegment(chart, mp, startP.X, startP.Y, newX, newYS)
                            }
                        }
                    }
                }else if plot.PlotType == "FiboFanline" {
                    inChart.StartMovePlot = SelectSegment(chart, mp, mpx1, mpy1, mpx2, mpy2)
                    if !inChart.StartMovePlot {
                        if mpx1 != mpx2 && mpy1 != mpy2 {
                            firstP := CreatePoint(mpx2, mpy2 - (mpy2 - mpy1) * 0.382)
                            secondP := CreatePoint(mpx2, mpy2 - (mpy2 - mpy1) * 0.5)
                            thirdP := CreatePoint(mpx2, mpy2 - (mpy2 - mpy1) * 0.618)
                            startP := CreatePoint(mpx1, mpy1)
                            var listP []FCPoint
                            listP = append(listP, firstP)
                            listP = append(listP, secondP)
                            listP = append(listP, thirdP)
                            listSize := len(listP)
                            for j := 0; j < listSize; j++ {
                                LineXY(chart, startP.X, startP.Y, listP[j].X, listP[j].Y, 0, 0)
                                newX := 0.0
                                newY := 0.0
                                if mpx2 > mpx1 {
                                    newY = inChart.KChart * (chart.Size.Cx - inChart.RightVScaleWidth) + inChart.BChart
                                    newX = (chart.Size.Cx - inChart.RightVScaleWidth)
                                }else {
                                    newY = inChart.BChart
                                    newX = inChart.LeftVScaleWidth
                                }
                                inChart.StartMovePlot = SelectSegment(chart, mp, startP.X, startP.Y, newX, newY)
                                if inChart.StartMovePlot {
                                    break
                                }
                            }
                        }
                    }
                }else if plot.PlotType == "FiboTimezone" {
                    fValue := 1
                    aIndex := index1
                    pos := 1
                    divHeight := GetCandleDivHeight(chart)
                    inChart.StartMovePlot = SelectSegment(chart, mp, mpx1, 0, mpx1, divHeight)
                    if !inChart.StartMovePlot {
                        for{
                            if aIndex + fValue <= inChart.LastVisibleIndex{
                                fValue = FibonacciValue(pos)
                                newIndex := aIndex + fValue
                                newX := GetChartX(chart, newIndex)
                                inChart.StartMovePlot = SelectSegment(chart, mp, newX, 0, newX, divHeight)
                                if inChart.StartMovePlot {
                                    break
                                }
                                pos += 1
                            }else{
                                break
                            }
                        }
                    }
                }else if plot.PlotType == "Percent" {
                    list := GetPercentParams(mpy1, mpy2)
                    for j := 0; j < len(list); j++ {
                        inChart.StartMovePlot = SelectSegment(chart, mp, inChart.LeftVScaleWidth, list[j], chart.Size.Cx - inChart.RightVScaleWidth, list[j])
                        if inChart.StartMovePlot {
                            break
                        }
                    }
                }
                if inChart.StartMovePlot {
                    sPlot = plot
                    plot.StartKey1 = plot.Key1
                    plot.StartValue1 = plot.Value1
                    plot.StartKey2 = plot.Key2
                    plot.StartValue2 = plot.Value2
                    plot.StartKey3 = plot.Key3
                    plot.StartValue3 = plot.Value3
                    break
                }
            }
        }
    }
    return sPlot
}

/*
* 计算线性回归上下限
* chart:图表
* plot:画线
* a:直线k
* b:直线b
*/
func GetLRBandRange(chart *FCView, plot *FCPlot, a float64, b float64) {
    inChart := chart.GetChart()
    bIndex := GetChartIndexByDate(chart, plot.Key1)
    eIndex := GetChartIndexByDate(chart, plot.Key2)
    tempBIndex := int(math.Min(float64(bIndex), float64(eIndex)))
    tempEIndex := int(math.Max(float64(bIndex), float64(eIndex)))
    bIndex = tempBIndex
    eIndex = tempEIndex
    var upList []float64
    var downList []float64
    for i := bIndex; i <= eIndex; i++ {
        high := inChart.Data[i].High
        low := inChart.Data[i].Low
        midValue := float64(i - bIndex + 1) * a + b
        upList = append(upList, high - midValue)
        downList = append(downList, midValue - low)
    }
    inChart.UpSubValue = MaxValue(upList)
    inChart.DownSubValue = MaxValue(downList)
}

/*
* 根据位置计算索引
* chart:图表
* mp:坐标
*/
func GetChartIndex(chart *FCView, mp FCPoint)(int){
    inChart := chart.GetChart()
    if len(inChart.Data) == 0{
        return -1
    }
    if mp.X <= 0 {
        return 0
    }
    intX := int(mp.X - inChart.LeftVScaleWidth - inChart.HScalePixel - inChart.OffsetX)
    if intX < 0{
        intX = 0
    }
    index := inChart.FirstVisibleIndex + int(float64(intX) / inChart.HScalePixel)
    if inChart.HScalePixel > 1{
        if intX % int(inChart.HScalePixel) != 0 {
            index += 1
        }
    }
    if index < 0 {
        index = 0
    } else if index > len(inChart.Data) - 1 {
        index = len(inChart.Data) - 1
    }
    return index
}

/*
* 获取最大显示记录条数
* chart:图表
* hScalePixel:间隔
* pureH:横向距离
*/
func GetChartMaxVisibleCount(chart *FCView, hScalePixel float64, pureH float64)(int){
    count := int((pureH - hScalePixel) / hScalePixel)
    if count < 0 {
        count = 0
    }
    return count
}

/*
* 获取图表层的高度
* chart:图表
*/
func GetCandleDivHeight(chart *FCView)(float64) {
    inChart := chart.GetChart()
    height := chart.Size.Cy - inChart.HScaleHeight
    if height > 0 {
        return height * inChart.CandleDivPercent
    } else {
        return 0
    }
}

/*
* 获取成交量层的高度
* chart:图表
*/
func GetVolDivHeight(chart *FCView)(float64) {
    inChart := chart.GetChart()
    height := chart.Size.Cy - inChart.HScaleHeight
    if height > 0 {
        return height * inChart.VolDivPercent
    } else {
        return 0
    }
}

/*
* 获取指标层的高度
* chart:图表
*/
func GetIndDivHeight(chart *FCView)(float64) {
    inChart := chart.GetChart()
    height := chart.Size.Cy - inChart.HScaleHeight
    if height > 0 {
        return height * inChart.IndDivPercent
    } else {
        return 0
    }
}

/*
* 获取指标层2的高度
* chart:图表
*/
func GetIndDivHeight2(chart *FCView)(float64) {
    inChart := chart.GetChart()
    height := chart.Size.Cy - inChart.HScaleHeight
    if height > 0 {
        return height * inChart.IndDivPercent2
    } else {
        return 0
    }
}

/*
* 获取横向工作区
* chart:图表
*/
func GetChartWorkAreaWidth(chart *FCView)(float64) {
    inChart := chart.GetChart()
    return chart.Size.Cx - inChart.LeftVScaleWidth - inChart.RightVScaleWidth - inChart.RightSpace - inChart.OffsetX
}

/*
* 根据索引获取横坐标
* chart:图表
* index:索引
*/
func GetChartX(chart *FCView, index int)(float64) {
    inChart := chart.GetChart()
    return inChart.LeftVScaleWidth + float64(index - inChart.FirstVisibleIndex) * inChart.HScalePixel + inChart.HScalePixel / 2 + inChart.OffsetX
}

/*
* 根据日期获取索引
* chart:图表
* date:日期
*/
func GetChartIndexByDate(chart *FCView, date float64)(int) {
    inChart := chart.GetChart()
    index := -1
    if len(inChart.Data) > 0{
        for i := 0; i < len(inChart.Data); i++ {
            if inChart.Data[i].Date == date {
                index = i
                break
            }
        }
    }
    return index
}

/*
* 根据索引获取日期
* chart:图表
* index:索引
*/
func GetChartDateByIndex(chart *FCView, index int)(float64) {
    date := 0.0
    inChart := chart.GetChart()
    if len(inChart.Data) > 0{
        if index >= 0 && index < len(inChart.Data) {
            date = inChart.Data[index].Date
        }
    }
    return date
}

/*
* 计算数值在层中的位置
* chart:图表
* divIndex:所在层
* chart:数值
*/
func GetChartY(chart *FCView, divIndex int, value float64)(float64) {
    inChart := chart.GetChart()
    if divIndex == 0 {
        if inChart.CandleMax > inChart.CandleMin {
            cValue := value
            cMax := inChart.CandleMax
            cMin := inChart.CandleMin
            if inChart.VScaleType != "standard" {
                if cValue > 0 {
                    cValue = math.Log(cValue)
                } else if cValue < 0 {
                    cValue = -math.Log(math.Abs(cValue))
                }
                if cMax > 0 {
                    cMax = math.Log(cMax)
                } else if cMax < 0 {
                    cMax = -math.Log(math.Abs(cMax))
                }
                if cMin > 0 {
                    cMin = math.Log(cMin)
                } else if cMin < 0 {
                    cMin = -math.Log(math.Abs(cMin))
                }
            }
            rate := (cValue - cMin) / (cMax - cMin)
            divHeight := GetCandleDivHeight(chart)
            return divHeight - inChart.CandlePaddingBottom - (divHeight - inChart.CandlePaddingTop - inChart.CandlePaddingBottom) * rate
        } else {
            return 0
        }
    } else if divIndex == 1 {
        if inChart.VolMax > inChart.VolMin {
            rate := (value - inChart.VolMin) / (inChart.VolMax - inChart.VolMin)
            candleHeight := GetCandleDivHeight(chart)
            volHeight := GetVolDivHeight(chart)
            return candleHeight + volHeight - inChart.VolPaddingBottom - (volHeight - inChart.VolPaddingTop - inChart.VolPaddingBottom) * rate
        } else {
            return 0
        }
    } else if divIndex == 2 {
        if inChart.IndMax > inChart.IndMin {
            rate := (value - inChart.IndMin) / (inChart.IndMax - inChart.IndMin)
            candleHeight := GetCandleDivHeight(chart)
            volHeight := GetVolDivHeight(chart)
            indHeight := GetIndDivHeight(chart)
            return candleHeight + volHeight + indHeight - inChart.IndPaddingBottom - (indHeight - inChart.IndPaddingTop - inChart.IndPaddingBottom) * rate
        } else {
            return 0
        }
    }else if divIndex == 3 {
        if inChart.IndMax2 > inChart.IndMin2 {
            rate := (value - inChart.IndMin2) / (inChart.IndMax2 - inChart.IndMin2)
            candleHeight := GetCandleDivHeight(chart)
            volHeight := GetVolDivHeight(chart)
            indHeight := GetIndDivHeight(chart)
            indHeight2 := GetIndDivHeight2(chart)
            return candleHeight + volHeight + indHeight + indHeight2 - inChart.IndPaddingBottom2 - (indHeight2 - inChart.IndPaddingTop2 - inChart.IndPaddingBottom2) * rate
        } else {
            return 0
        }
    }
    return 0
}

/*
* 计算数值在层中的右轴位置
* chart:图表
* divIndex:所在层
* chart:数值
*/
func GetChartYInRight(chart *FCView, divIndex int, value float64)(float64) {
    inChart := chart.GetChart()
    if divIndex == 0 {
        if inChart.CandleMaxRight > inChart.CandleMinRight {
            cValue := value
            cMax := inChart.CandleMaxRight
            cMin := inChart.CandleMinRight
            if inChart.VScaleType != "standard" {
                if cValue > 0 {
                    cValue = math.Log(cValue)
                } else if cValue < 0 {
                    cValue = -math.Log(math.Abs(cValue))
                }
                if cMax > 0 {
                    cMax = math.Log(cMax)
                } else if cMax < 0 {
                    cMax = -math.Log(math.Abs(cMax))
                }
                if cMin > 0 {
                    cMin = math.Log(cMin)
                } else if cMin < 0 {
                    cMin = -math.Log(math.Abs(cMin))
                }
            }
            rate := (cValue - cMin) / (cMax - cMin)
            divHeight := GetCandleDivHeight(chart)
            return divHeight - inChart.CandlePaddingBottom - (divHeight - inChart.CandlePaddingTop - inChart.CandlePaddingBottom) * rate
        } else {
            return 0
        }
    } else if divIndex == 1 {
        if inChart.VolMaxRight > inChart.VolMinRight {
            rate := (value - inChart.VolMinRight) / (inChart.VolMaxRight - inChart.VolMinRight)
            candleHeight := GetCandleDivHeight(chart)
            volHeight := GetVolDivHeight(chart)
            return candleHeight + volHeight - inChart.VolPaddingBottom - (volHeight - inChart.VolPaddingTop - inChart.VolPaddingBottom) * rate
        } else {
            return 0
        }
    } else if divIndex == 2{
        if inChart.IndMaxRight > inChart.IndMinRight {
            rate := (value - inChart.IndMinRight) / (inChart.IndMaxRight - inChart.IndMinRight)
            candleHeight := GetCandleDivHeight(chart)
            volHeight := GetVolDivHeight(chart)
            indHeight := GetIndDivHeight(chart)
            return candleHeight + volHeight + indHeight - inChart.IndPaddingBottom - (indHeight - inChart.IndPaddingTop - inChart.IndPaddingBottom) * rate
        } else {
            return 0
        }
    }else if divIndex == 3 {
        if inChart.IndMax2Right > inChart.IndMin2Right {
            rate := (value - inChart.IndMin2Right) / (inChart.IndMax2Right - inChart.IndMin2Right)
            candleHeight := GetCandleDivHeight(chart)
            volHeight := GetVolDivHeight(chart)
            indHeight := GetIndDivHeight(chart)
            indHeight2 := GetIndDivHeight2(chart)
            return candleHeight + volHeight + indHeight + indHeight2 - inChart.IndPaddingBottom2 - (indHeight2 - inChart.IndPaddingTop2 - inChart.IndPaddingBottom2) * rate
        } else {
            return 0
        }
    }
    return 0
}

/*
* 根据坐标获取对应的值
* chart:图表
* point:坐标
*/
func GetChartValue(chart *FCView, point FCPoint)(float64) {
    inChart := chart.GetChart()
    candleHeight := GetCandleDivHeight(chart)
    volHeight := GetVolDivHeight(chart)
    indHeight := GetIndDivHeight(chart)
    indHeight2 := GetIndDivHeight(chart)
    if point.Y <= candleHeight {
        if candleHeight - inChart.CandlePaddingTop - inChart.CandlePaddingBottom > 0{
            rate := (candleHeight - inChart.CandlePaddingBottom - point.Y) / (candleHeight - inChart.CandlePaddingTop - inChart.CandlePaddingBottom)
            cMin := inChart.CandleMin
            cMax := inChart.CandleMax
            if inChart.VScaleType != "standard" {
                if cMax > 0 {
                    cMax = math.Log(cMax)
                } else if cMax < 0 {
                    cMax = -math.Log(math.Abs(cMax))
                }
                if cMin > 0 {
                    cMin = math.Log(cMin)
                } else if cMin < 0 {
                    cMin = -math.Log(math.Abs(cMin))
                }
            }
            result := cMin + (cMax - cMin) * rate
            if inChart.VScaleType != "standard" {
                return math.Pow(10, result)
            } else {
                return result
            }
        }
    }else if point.Y > candleHeight && point.Y <= candleHeight + volHeight {
        if volHeight - inChart.VolPaddingTop - inChart.VolPaddingBottom > 0{
            rate := (volHeight - inChart.VolPaddingBottom - (point.Y - candleHeight)) / (volHeight - inChart.VolPaddingTop - inChart.VolPaddingBottom)
            return inChart.VolMin + (inChart.VolMax - inChart.VolMin) * rate
        }
    } else if point.Y > candleHeight + volHeight && point.Y <= candleHeight + volHeight + indHeight {
        if indHeight - inChart.IndPaddingTop - inChart.IndPaddingBottom > 0{
            rate := (indHeight - inChart.IndPaddingBottom - (point.Y - candleHeight - volHeight)) / (indHeight - inChart.IndPaddingTop - inChart.IndPaddingBottom)
            return inChart.IndMin + (inChart.IndMax - inChart.IndMin) * rate
        }
    } else if point.Y > candleHeight + volHeight + indHeight && point.Y <= candleHeight + volHeight + indHeight + indHeight2 {
        if indHeight2 - inChart.IndPaddingTop2 - inChart.IndPaddingBottom2 > 0{
            rate := (indHeight2 - inChart.IndPaddingBottom2 - (point.Y - candleHeight - volHeight - indHeight)) / (indHeight2 - inChart.IndPaddingTop2 - inChart.IndPaddingBottom2)
            return inChart.IndMin2 + (inChart.IndMax2 - inChart.IndMin2) * rate
        }
    }
    return 0
}

/*
* 根据坐标获取对应的值
* chart:图表
* point:坐标
*/
func GetCandleDivValue(chart *FCView, point FCPoint)(float64) {
    inChart := chart.GetChart()
    candleHeight := GetCandleDivHeight(chart)
    rate := 0.0
    if candleHeight - inChart.CandlePaddingTop - inChart.CandlePaddingBottom > 0{
        rate = (candleHeight - inChart.CandlePaddingBottom - point.Y) / (candleHeight - inChart.CandlePaddingTop - inChart.CandlePaddingBottom)
    }
    cMin := inChart.CandleMin
    cMax := inChart.CandleMax
    if inChart.VScaleType != "standard" {
        if cMax > 0 {
            cMax = math.Log(cMax)
        } else if cMax < 0 {
            cMax = -math.Log(math.Abs(cMax))
        }
        if cMin > 0 {
            cMin = math.Log(cMin)
        } else if cMin < 0 {
            cMin = -math.Log(math.Abs(cMin))
        }
    }
    result := cMin + (cMax - cMin) * rate
    if inChart.VScaleType != "standard" {
        return math.Pow(10, result)
    } else {
        return result
    }
}

/*
* 检查最后可见索引
* chart:图表
*/
func CheckChartLastVisibleIndex(chart *FCView) {
    inChart := chart.GetChart()
    dataCount := len(inChart.Data)
    workingAreaWidth := GetChartWorkAreaWidth(chart)
    maxVisibleRecord := GetChartMaxVisibleCount(chart, inChart.HScalePixel, workingAreaWidth)
    if inChart.FirstVisibleIndex < 0{
        inChart.FirstVisibleIndex = 0
    }
    if (inChart.LastVisibleIndex >= inChart.FirstVisibleIndex + maxVisibleRecord - 1) || (inChart.LastVisibleIndex < dataCount - 1){
        inChart.LastVisibleIndex = inChart.FirstVisibleIndex + maxVisibleRecord - 1
    }
    if inChart.LastVisibleIndex > dataCount - 1{
        inChart.LastVisibleIndex = dataCount - 1
    }
    if len(inChart.Data) > 0 {
        inChart.LastVisibleKey = inChart.Data[inChart.LastVisibleIndex].Date
        if inChart.LastVisibleIndex == len(inChart.Data) - 1 {
            inChart.LastRecordIsVisible = true
        } else {
            inChart.LastRecordIsVisible = false
        }
    } else {
        inChart.LastVisibleKey = 0
        inChart.LastRecordIsVisible = true
    }
}

/*
* 自动设置首先可见和最后可见的记录号
* chart:图表
*/
func ResetChartVisibleRecord(chart *FCView) {
    inChart := chart.GetChart()
    rowsCount := len(inChart.Data)
    workingAreaWidth := GetChartWorkAreaWidth(chart)
    if inChart.AutoFillHScale {
        if workingAreaWidth > 0 && rowsCount > 0 {
            inChart.HScalePixel = workingAreaWidth / float64(rowsCount)
            inChart.FirstVisibleIndex = 0
            inChart.LastVisibleIndex = rowsCount - 1
        }
    } else {
        maxVisibleRecord := GetChartMaxVisibleCount(chart, inChart.HScalePixel, workingAreaWidth)
        //没数据时重置
        if rowsCount == 0 {
            inChart.FirstVisibleIndex = -1
            inChart.LastVisibleIndex = -1
        } else {
            //数据不足一屏时
            if rowsCount < maxVisibleRecord {
                inChart.LastVisibleIndex = rowsCount - 1
                inChart.FirstVisibleIndex = 0
            }else {
                //显示中间的数据时
                if inChart.FirstVisibleIndex != -1 && inChart.LastVisibleIndex != -1 && !inChart.LastRecordIsVisible {
                    index := GetChartIndexByDate(chart, inChart.LastVisibleKey)
                    if index != -1 {
                        inChart.LastVisibleIndex = index
                    }
                    inChart.FirstVisibleIndex = inChart.LastVisibleIndex - maxVisibleRecord + 1
                    if inChart.FirstVisibleIndex < 0 {
                        inChart.FirstVisibleIndex = 0
                        inChart.LastVisibleIndex = inChart.FirstVisibleIndex + maxVisibleRecord
                        CheckChartLastVisibleIndex(chart)
                    }
                } else {
                    //第一条或最后一条数据被显示时
                    inChart.LastVisibleIndex = rowsCount - 1
                    inChart.FirstVisibleIndex = inChart.LastVisibleIndex - maxVisibleRecord + 1
                    if inChart.FirstVisibleIndex > inChart.LastVisibleIndex {
                        inChart.FirstVisibleIndex = inChart.LastVisibleIndex
                    }
                }
            }
        }
    }
}

/*
* 设置可见索引
* chart:图表
* FirstVisibleIndex:起始索引
* LastVisibleIndex:结束索引
*/
func SetChartVisibleIndex(chart *FCView, FirstVisibleIndex int, LastVisibleIndex int) {
    inChart := chart.GetChart()
    xScalePixel := GetChartWorkAreaWidth(chart) / float64(LastVisibleIndex - FirstVisibleIndex + 1)
    if xScalePixel < 1000000 {
        inChart.FirstVisibleIndex = FirstVisibleIndex
        inChart.LastVisibleIndex = LastVisibleIndex
        //设置最后一条记录是否可见
        if LastVisibleIndex != len(inChart.Data) - 1 {
            inChart.LastRecordIsVisible = false
        } else {
            inChart.LastRecordIsVisible = true
        }
        inChart.HScalePixel = xScalePixel
        CheckChartLastVisibleIndex(chart)
    }
}

/*
* 清除图形
* chart:图表
* paint:绘图对象
* clipRect:裁剪区域
*/
func DrawChart(chart *FCView, paint *FCPaint, clipRect FCRect) {
    inChart := chart.GetChart()
    if chart.BackColor != "none" {
        paint.FillRect(chart.BackColor, 0, 0, chart.Size.Cx, chart.Size.Cy)
    }
    if inChart.OnPaintChartScale != nil{
        inChart.OnPaintChartScale(chart, paint, clipRect)
    }else if paint.OnPaintChartScale != nil{
        paint.OnPaintChartScale(chart, paint, clipRect)
    }else{
        DrawChartScale(chart, paint, clipRect)
    }
    if inChart.OnPaintChartStock != nil{
        inChart.OnPaintChartStock(chart, paint, clipRect)
    }else if paint.OnPaintChartStock != nil{
        paint.OnPaintChartStock(chart, paint, clipRect)
    }else{
        DrawChartStock(chart, paint, clipRect)
    }
    if inChart.OnPaintChartPlot != nil{
        inChart.OnPaintChartPlot(chart, paint, clipRect)
    }else if paint.OnPaintChartPlot != nil{
        paint.OnPaintChartPlot(chart, paint, clipRect)
    }else{
        DrawChartPlot(chart, paint, clipRect)
    }
    if inChart.OnPaintChartCrossLine != nil{
        inChart.OnPaintChartCrossLine(chart, paint, clipRect)
    }else if paint.OnPaintChartCrossLine != nil{
        paint.OnPaintChartCrossLine(chart, paint, clipRect)
    }else{
        DrawChartCrossLine(chart, paint, clipRect)
    }
    if chart.BorderColor != "none" {
        paint.DrawRect(chart.BorderColor, inChart.LineWidthChart, 0, 0, 0, chart.Size.Cx, chart.Size.Cy)
    }
}

/*
* 计算坐标轴
* min:最小值
* max:最大值
* yLen:长度
* maxSpan:最大间隔
* minSpan:最小间隔
* defCount:数量
*/
func ChartGridScale(chart *FCView, min float64, max float64, yLen int, maxSpan float64, minSpan float64, defCount int){
    inChart := chart.GetChart()
    sub := max - min
    nMinCount := int(math.Ceil(float64(yLen) / maxSpan))
    nMaxCount := int(math.Floor(float64(yLen) / minSpan))
    nCount := defCount
    logStep := sub / float64(nCount)
    start := false
    divisor := 0.0
    i := 15
    nTemp := 0
    inChart.GridStepChart = 0
    inChart.GridDigitChart = 0
    if nMinCount > nCount{
        nCount =  nMinCount
    }
    if nMaxCount < nCount{
        nCount = nMaxCount
    }
    if nCount < 1{
        nCount =  1
    }
    for{
        if i >= -6{
            divisor = math.Pow(10.0, float64(i))
            if divisor < 1 {
                inChart.GridDigitChart += 1
            }
            nTemp = int(math.Floor(logStep / divisor))
            if start {
                if nTemp < 4 {
                    if (inChart.GridDigitChart > 0) {
                        inChart.GridDigitChart -= 1
                    }
                } else if nTemp >= 4 && nTemp <= 6 {
                    nTemp = 5
                    inChart.GridStepChart += float64(nTemp) * divisor
                } else {
                    inChart.GridStepChart += 10 * divisor
                    if inChart.GridDigitChart > 0 {
                        inChart.GridDigitChart -= 1
                    }
                }
                break
            } else if nTemp > 0{
                inChart.GridStepChart = float64(nTemp) * divisor + inChart.GridStepChart
                logStep -= inChart.GridStepChart
                start = true
            }
            i -= 1
        }else{
            break
        }
    }
}

/*
* 缩小
* chart:图表
*/
func ZoomOutChart(chart *FCView) {
    inChart := chart.GetChart()
    if !inChart.AutoFillHScale {
        hScalePixel := inChart.HScalePixel
        oldX := GetChartX(chart, inChart.CrossStopIndex)
        if inChart.ShowCrossLine && inChart.TargetOldX == 0{
			inChart.TargetOldX = oldX
		}
        pureH := GetChartWorkAreaWidth(chart)
        oriMax := -1
        max := -1
        deal := 0
        dataCount := len(inChart.Data)
        findex := inChart.FirstVisibleIndex
        lindex := inChart.LastVisibleIndex
        if hScalePixel < pureH {
            oriMax = GetChartMaxVisibleCount(chart, hScalePixel, pureH)
            if dataCount < oriMax {
                deal = 1
            }
            if hScalePixel > 3 {
                hScalePixel += 1
            } else {
                if hScalePixel == 1 {
                    hScalePixel = 2
                } else {
                    hScalePixel = hScalePixel * 1.5
                    if hScalePixel > 3 {
                        hScalePixel = float64(int(hScalePixel))
                    }
                }
            }
            max = GetChartMaxVisibleCount(chart, hScalePixel, pureH)
            if dataCount >= max {
                if deal == 1 {
                    lindex = dataCount - 1
                }
                findex = lindex - max + 1
                if (findex < 0) {
                    findex = 0
                }
            }
        }
        inChart.HScalePixel = hScalePixel
        if inChart.ShowCrossLine{
			sX := inChart.TargetOldX
			findex = inChart.CrossStopIndex
            for{
                if sX < inChart.LeftVScaleWidth + inChart.HScalePixel / 2{
                    break
                }
                findex = findex - 1
				inChart.OffsetX = sX - inChart.LeftVScaleWidth - inChart.HScalePixel / 2
				sX = sX - inChart.HScalePixel
            }
			findex = findex + 1
		}
		inChart.FirstVisibleIndex = findex
		inChart.LastVisibleIndex = lindex
        CheckChartLastVisibleIndex(chart)
        if inChart.OnCalculateChartMaxMin != nil{
            inChart.OnCalculateChartMaxMin(chart)
        }else if chart.GetPaint().OnCalculateChartMaxMin != nil{
            chart.GetPaint().OnCalculateChartMaxMin(chart)
        }else{
            CalculateChartMaxMin(chart)
        }
    }
}

/*
* 放大
* chart:图表
*/
func ZoomInChart(chart *FCView) {
    inChart := chart.GetChart()
    if !inChart.AutoFillHScale {
        hScalePixel := inChart.HScalePixel
        oldX := GetChartX(chart, inChart.CrossStopIndex)
        if inChart.ShowCrossLine && inChart.TargetOldX2 == 0{
			inChart.TargetOldX2 = oldX
		}
        pureH := GetChartWorkAreaWidth(chart)
        max := -1
        dataCount := len(inChart.Data)
        findex := inChart.FirstVisibleIndex
        lindex := inChart.LastVisibleIndex
        if hScalePixel > 3 {
            hScalePixel -= 1
        } else {
            hScalePixel = hScalePixel * 2 / 3
            if hScalePixel > 3 {
                hScalePixel = float64(int(hScalePixel))
            }
        }
        max = GetChartMaxVisibleCount(chart, hScalePixel, pureH)
        if max >= dataCount {
            if hScalePixel < 1 {
                hScalePixel = pureH / float64(max)
            }
            findex = 0
            lindex = dataCount - 1
        } else {
            findex = lindex - max + 1
            if (findex < 0) {
                findex = 0
            }
        }
        inChart.HScalePixel = hScalePixel
        if inChart.ShowCrossLine{
			sX := inChart.TargetOldX2
			findex = inChart.CrossStopIndex
            for{
                if sX < inChart.LeftVScaleWidth + inChart.HScalePixel / 2{
                    break
                }
                findex = findex - 1
				inChart.OffsetX = sX - inChart.LeftVScaleWidth - inChart.HScalePixel / 2
				sX = sX - inChart.HScalePixel
            }
			findex = findex + 1
		}
		inChart.FirstVisibleIndex = findex
		inChart.LastVisibleIndex = lindex
        CheckChartLastVisibleIndex(chart)
        if inChart.OnCalculateChartMaxMin != nil{
            inChart.OnCalculateChartMaxMin(chart)
        }else if chart.GetPaint().OnCalculateChartMaxMin != nil{
            chart.GetPaint().OnCalculateChartMaxMin(chart)
        }else{
            CalculateChartMaxMin(chart)
        }
    }
}


/*
* 绘制刻度
* chart:图表
* paint:绘图对象
* clipRect:裁剪区域
*/
func DrawChartScale(chart *FCView, paint *FCPaint, clipRect FCRect) {
    inChart := chart.GetChart()
    if inChart.LeftVScaleWidth > 0 {
        paint.DrawLine(inChart.ScaleColor, inChart.LineWidthChart, 0, inChart.LeftVScaleWidth, 0, inChart.LeftVScaleWidth, chart.Size.Cy - inChart.HScaleHeight)
    }
    if inChart.RightVScaleWidth > 0 {
        paint.DrawLine(inChart.ScaleColor, inChart.LineWidthChart, 0, chart.Size.Cx - inChart.RightVScaleWidth, 0, chart.Size.Cx - inChart.RightVScaleWidth, chart.Size.Cy - inChart.HScaleHeight)
    }
    if inChart.HScaleHeight > 0 {
        paint.DrawLine(inChart.ScaleColor, inChart.LineWidthChart, 0, 0, chart.Size.Cy - inChart.HScaleHeight, chart.Size.Cx, chart.Size.Cy - inChart.HScaleHeight)
    }
    candleDivHeight := GetCandleDivHeight(chart)
    volDivHeight := GetVolDivHeight(chart)
    indDivHeight := GetIndDivHeight(chart)
    indDivHeight2 := GetIndDivHeight2(chart)
    if volDivHeight > 0 {
        paint.DrawLine(inChart.ScaleColor, inChart.LineWidthChart, 0, inChart.LeftVScaleWidth, candleDivHeight, chart.Size.Cx - inChart.RightVScaleWidth, candleDivHeight)
    }
    if indDivHeight > 0 {
        paint.DrawLine(inChart.ScaleColor, inChart.LineWidthChart, 0, inChart.LeftVScaleWidth, candleDivHeight + volDivHeight, chart.Size.Cx - inChart.RightVScaleWidth, candleDivHeight + volDivHeight)
    }
    if indDivHeight2 > 0 {
        paint.DrawLine(inChart.ScaleColor, inChart.LineWidthChart, 0, inChart.LeftVScaleWidth, candleDivHeight + volDivHeight + indDivHeight, chart.Size.Cx - inChart.RightVScaleWidth, candleDivHeight + volDivHeight + indDivHeight)
    }
    if len(inChart.Data) == 0{
        return
    }
    topPoint := CreatePoint(0, 20)
    bottomPoint := CreatePoint(0, candleDivHeight - 10)
    candleMax := GetChartValue(chart, topPoint)
    candleMin := GetChartValue(chart, bottomPoint)
    ChartGridScale(chart, candleMin, candleMax, int((candleDivHeight - inChart.CandlePaddingTop - inChart.CandlePaddingBottom) / 2), inChart.VScaleDistance, inChart.VScaleDistance / 2, int((candleDivHeight - inChart.CandlePaddingTop - inChart.CandlePaddingBottom) / inChart.VScaleDistance))
    if inChart.GridStepChart > 0 {
        var drawValues []float64
        isTrend := false
        if inChart.Cycle == "trend"{
            isTrend = true
        }
        firstOpen := inChart.FirstOpen
        if isTrend {
            if(firstOpen == 0){
                firstOpen = inChart.Data[inChart.FirstVisibleIndex].Close
            }
            subValue := (candleMax - candleMin)
            count := int((candleDivHeight - inChart.CandlePaddingTop - inChart.CandlePaddingBottom) / inChart.VScaleDistance)
            if count > 0 {
                subValue /= float64(count)
            }
            start := firstOpen
            for{
                if start < candleMax {
                    start += subValue
                    if start <= candleMax {
                        drawValues = append(drawValues, start)
                    }
                }else{
                    break
                }
            }
            start = firstOpen
            for{
                if start > candleMin {
                    start -= subValue
                    if start >= candleMin {
                        drawValues = append(drawValues, start)
                    }
                }else{
                    break
                }
            }
        } else {
            start := 0.0
            if candleMin >= 0 {
                for{
                    if start + inChart.GridStepChart < candleMin {
                        start += inChart.GridStepChart
                    }else{
                        break
                    }
                }
            } else {
                for{
                    if start - inChart.GridStepChart > candleMin {
                        start -= inChart.GridStepChart
                    }else{
                        break
                    }
                }
            }
            for{
                if start <= candleMax {
                    if start > candleMin {
                        drawValues = append(drawValues, start)
                    }
                    start += inChart.GridStepChart
                }else{
                    break
                }
            }
        }
        drawValues = append(drawValues, firstOpen)
        for i:= 0; i < len(drawValues); i++ {
            start := drawValues[i]
            hAxisY := GetChartY(chart, 0, start)
            if hAxisY < 1 || hAxisY > candleDivHeight {
                continue
            }
            paint.DrawLine(inChart.GridColor, inChart.LineWidthChart, 0, inChart.LeftVScaleWidth, hAxisY, chart.Size.Cx - inChart.RightVScaleWidth, hAxisY)
            paint.DrawLine(inChart.ScaleColor, inChart.LineWidthChart, 0, inChart.LeftVScaleWidth - 8, hAxisY, inChart.LeftVScaleWidth, hAxisY)
            paint.DrawLine(inChart.ScaleColor, inChart.LineWidthChart, 0, chart.Size.Cx - inChart.RightVScaleWidth, hAxisY, chart.Size.Cx - inChart.RightVScaleWidth + 8, hAxisY)
            
            DrawText := ToFixed(start, inChart.CandleDigit)
            tSize := paint.TextSize(DrawText, chart.Font)
            if isTrend {
                diffRange := ((start - firstOpen) / firstOpen * 100)
                diffRangeStr := ToFixed(diffRange, 2) + "%"
                if diffRange >= 0 {
                    paint.DrawText(diffRangeStr, inChart.UpColor, chart.Font, chart.Size.Cx - inChart.RightVScaleWidth + 10, hAxisY - tSize.Cy / 2)
                } else {
                    paint.DrawText(diffRangeStr,inChart.DownColor, chart.Font, chart.Size.Cx - inChart.RightVScaleWidth + 10, hAxisY - tSize.Cy / 2)
                }
            } else {
                paint.DrawText(DrawText, chart.TextColor, chart.Font, chart.Size.Cx - inChart.RightVScaleWidth + 10, hAxisY - tSize.Cy / 2)
            }
            paint.DrawText(DrawText, chart.TextColor, chart.Font, inChart.LeftVScaleWidth - tSize.Cx - 10, hAxisY - tSize.Cy / 2)
        }
        topPoint = CreatePoint(0, candleDivHeight + 10)
        bottomPoint = CreatePoint(0, candleDivHeight + volDivHeight - 10)
        volMax := GetChartValue(chart, topPoint)
        volMin := GetChartValue(chart, bottomPoint)
        ChartGridScale(chart, volMin, volMax, int((volDivHeight - inChart.VolPaddingTop - inChart.VolPaddingBottom) / 2), inChart.VScaleDistance, inChart.VScaleDistance / 2, int((volDivHeight - inChart.VolPaddingTop - inChart.VolPaddingBottom) / inChart.VScaleDistance))
        if inChart.GridStepChart > 0 {
            start := 0.0
            if volMin >= 0 {
                for{
                    if start + inChart.GridStepChart < volMin {
                        start += inChart.GridStepChart
                    }else{
                        break
                    }
                }
            } else {
                for{
                    if start - inChart.GridStepChart > volMin {
                        start -= inChart.GridStepChart
                    }else{
                        break
                    }
                }
            }
            for{
                if start <= volMax {
                    if start > volMin {
                        hAxisY := GetChartY(chart, 1, start)
                        if hAxisY < candleDivHeight || hAxisY > candleDivHeight + volDivHeight {
                            start += inChart.GridStepChart
                            continue
                        }
                        paint.DrawLine(inChart.GridColor, inChart.LineWidthChart, 0, inChart.LeftVScaleWidth, hAxisY, chart.Size.Cx - inChart.RightVScaleWidth, hAxisY)
                        paint.DrawLine(inChart.ScaleColor, inChart.LineWidthChart, 0, inChart.LeftVScaleWidth - 8, hAxisY, inChart.LeftVScaleWidth, hAxisY)
                        paint.DrawLine(inChart.ScaleColor, inChart.LineWidthChart, 0, chart.Size.Cx - inChart.RightVScaleWidth, hAxisY, chart.Size.Cx - inChart.RightVScaleWidth + 8, hAxisY)
                        DrawText := ToFixed((start / float64(inChart.Magnitude)), inChart.VolDigit)
                        tSize := paint.TextSize(DrawText, chart.Font)
                        paint.DrawText(DrawText, chart.TextColor, chart.Font, chart.Size.Cx - inChart.RightVScaleWidth + 10, hAxisY - tSize.Cy / 2)
                        paint.DrawText(DrawText, chart.TextColor, chart.Font, inChart.LeftVScaleWidth - tSize.Cx - 10, hAxisY - tSize.Cy / 2)
                    }
                    start += inChart.GridStepChart
                }else{
                    break
                }
            }
        }
    }
    if indDivHeight > 0 {
        topPoint := CreatePoint(0, candleDivHeight + volDivHeight + 10)
        bottomPoint := CreatePoint(0, candleDivHeight + volDivHeight + indDivHeight - 10)
        indMax := GetChartValue(chart, topPoint)
        indMin := GetChartValue(chart, bottomPoint)
        ChartGridScale(chart, indMin, indMax, int((indDivHeight - inChart.IndPaddingTop - inChart.IndPaddingBottom) / 2), inChart.VScaleDistance, inChart.VScaleDistance / 2, int((indDivHeight - inChart.IndPaddingTop - inChart.IndPaddingBottom) / inChart.VScaleDistance))
        if inChart.GridStepChart > 0 {
            start := 0.0
            if indMin >= 0 {
                for{
                    if start + inChart.GridStepChart < indMin {
                        start += inChart.GridStepChart
                    }else{
                        break
                    }
                }
            } else {
                for{
                    if start - inChart.GridStepChart > indMin {
                        start -= inChart.GridStepChart
                    }else{
                        break
                    }
                }
            }
            for{
                if start <= indMax {
                    if start > indMin {
                        hAxisY := GetChartY(chart, 2, start)
                        if hAxisY < candleDivHeight + volDivHeight || hAxisY > candleDivHeight + volDivHeight + indDivHeight {
                            start += inChart.GridStepChart
                            continue
                        }
                        paint.DrawLine(inChart.GridColor, inChart.LineWidthChart, 0, inChart.LeftVScaleWidth, hAxisY, chart.Size.Cx - inChart.RightVScaleWidth, hAxisY)
                        paint.DrawLine(inChart.ScaleColor, inChart.LineWidthChart, 0, inChart.LeftVScaleWidth - 8, hAxisY, inChart.LeftVScaleWidth, hAxisY)
                        paint.DrawLine(inChart.ScaleColor, inChart.LineWidthChart, 0, chart.Size.Cx - inChart.RightVScaleWidth, hAxisY, chart.Size.Cx - inChart.RightVScaleWidth + 8, hAxisY)
                        DrawText := ToFixed(start, inChart.IndDigit)
                        tSize := paint.TextSize(DrawText, chart.Font)
                        paint.DrawText(DrawText, chart.TextColor, chart.Font, chart.Size.Cx - inChart.RightVScaleWidth + 10, hAxisY - tSize.Cy / 2)
                        paint.DrawText(DrawText, chart.TextColor, chart.Font, inChart.LeftVScaleWidth - tSize.Cx - 10, hAxisY - tSize.Cy / 2)
                    }
                    start += inChart.GridStepChart
                }else{
                    break
                }
            }
        }
    }
    if indDivHeight2 > 0 {
        topPoint = CreatePoint(0, candleDivHeight + volDivHeight + indDivHeight + 10)
        bottomPoint = CreatePoint(0, candleDivHeight + volDivHeight + indDivHeight + indDivHeight2 - 10)
        indMax2 := GetChartValue(chart, topPoint)
        indMin2 := GetChartValue(chart, bottomPoint)
        ChartGridScale(chart, indMin2, indMax2, int((indDivHeight2 - inChart.IndPaddingTop2 - inChart.IndPaddingBottom2) / 2), inChart.VScaleDistance, inChart.VScaleDistance / 2, int((indDivHeight2 - inChart.IndPaddingTop2 - inChart.IndPaddingBottom2) / inChart.VScaleDistance))
        if inChart.GridStepChart > 0 {
            start := 0.0
            if indMin2 >= 0 {
                for{
                    if start + inChart.GridStepChart < indMin2 {
                        start += inChart.GridStepChart
                    }else{
                        break
                    }
                }
            } else {
                for{
                    if start - inChart.GridStepChart > indMin2 {
                        start -= inChart.GridStepChart
                    }else{
                        break
                    }
                }
            }
            for{
                if start <= indMax2 {
                    if start > indMin2 {
                        hAxisY := GetChartY(chart, 3, start)
                        if hAxisY < candleDivHeight + volDivHeight + indDivHeight || hAxisY > candleDivHeight + volDivHeight + indDivHeight + indDivHeight2 {
                            start += inChart.GridStepChart
                            continue
                        }
                        paint.DrawLine(inChart.GridColor, inChart.LineWidthChart, 0, inChart.LeftVScaleWidth, hAxisY, chart.Size.Cx - inChart.RightVScaleWidth, hAxisY)
                        paint.DrawLine(inChart.ScaleColor, inChart.LineWidthChart, 0, inChart.LeftVScaleWidth - 8, hAxisY, inChart.LeftVScaleWidth, hAxisY)
                        paint.DrawLine(inChart.ScaleColor, inChart.LineWidthChart, 0, chart.Size.Cx - inChart.RightVScaleWidth, hAxisY, chart.Size.Cx - inChart.RightVScaleWidth + 8, hAxisY)
                        DrawText := ToFixed(start, inChart.IndDigit)
                        tSize := paint.TextSize(DrawText, chart.Font)
                        paint.DrawText(DrawText, chart.TextColor,chart.Font, chart.Size.Cx - inChart.RightVScaleWidth + 10, hAxisY - tSize.Cy / 2)
                        paint.DrawText(DrawText, chart.TextColor,chart.Font, inChart.LeftVScaleWidth - tSize.Cx - 10, hAxisY - tSize.Cy / 2)
                    }
                    start += inChart.GridStepChart
                }else{
                    break
                }
            }
        }
    }
    if inChart.OnPaintChartHScale != nil{
        inChart.OnPaintChartHScale(chart, paint, clipRect)
    }else if paint.OnPaintChartHScale != nil{
        paint.OnPaintChartHScale(chart, paint, clipRect)
    }else{
        if len(inChart.Data) > 0 && inChart.HScaleHeight > 0 {
            dLeft := inChart.LeftVScaleWidth + 10
            i := inChart.FirstVisibleIndex
            for i = inChart.FirstVisibleIndex; i <= inChart.LastVisibleIndex; i++ {
                tm := time.Unix(int64(inChart.Data[i].Date / 1000), 0)
                xText := ""
                if len(inChart.HScaleFormat) > 0 {
                    xText = tm.Format(inChart.HScaleFormat)
                } else {
                    if inChart.Cycle == "day"{
                        xText = tm.Format("2006-01-02")
                    } else if inChart.Cycle == "minute" {
                        xText = tm.Format("2006/01/02 15:04")
                    } else if inChart.Cycle == "trend" {
                        xText = tm.Format("15:04")
                    }else if inChart.Cycle == "second" {
                        xText = tm.Format("15:04:05")
                    }else if inChart.Cycle == "tick"{
                        xText = ConvertIntToStr(i + 1)
                    }
                }
                tSize := paint.TextSize(xText, chart.Font)
                x := GetChartX(chart, i)
                dx := x - tSize.Cx / 2
                if dx > dLeft && dx < chart.Size.Cx - inChart.RightVScaleWidth - 10 {
                    paint.DrawLine(inChart.ScaleColor, inChart.LineWidthChart, 0, x, chart.Size.Cy - inChart.HScaleHeight, x, chart.Size.Cy - inChart.HScaleHeight + 8)
                    paint.DrawText(xText, chart.TextColor, chart.Font, dx, chart.Size.Cy - inChart.HScaleHeight + 8  - tSize.Cy / 2 + 7)
                    i = i + int((tSize.Cx + inChart.HScaleTextDistance) / inChart.HScalePixel) + 1
                }
            }
        }
    }
}

/*
* 绘制十字线
* chart:图表
* paint:绘图对象
* clipRect:裁剪区域
*/
func DrawChartCrossLine(chart *FCView, paint *FCPaint, clipRect FCRect) {
    inChart := chart.GetChart()
    if len(inChart.Data) == 0 {
        return
    }
    candleDivHeight := GetCandleDivHeight(chart)
    volDivHeight := GetVolDivHeight(chart)
    indDivHeight := GetIndDivHeight(chart)
    indDivHeight2 := GetIndDivHeight2(chart)
    crossLineIndex := inChart.CrossStopIndex
    if crossLineIndex == -1 || !inChart.ShowCrossLine{
        if inChart.LastValidIndex != -1{
            crossLineIndex = inChart.LastValidIndex
        }else{
            crossLineIndex = inChart.LastVisibleIndex
        }
    }
    if crossLineIndex == -1{
        return
    }
    if volDivHeight > 0 {
        var drawTitles []string
        var drawColors []string
        drawTitles = append(drawTitles, "VOL " + ToFixed(inChart.Data[crossLineIndex].Volume / float64(inChart.Magnitude), inChart.VolDigit))
        drawColors = append(drawColors, chart.TextColor)
        if len(inChart.Shapes)  > 0 {
            for i:= 0; i < len(inChart.Shapes); i++ {
                shape := inChart.Shapes[i]
                if shape.DivIndex == 1 {
                    if len(shape.Title) > 0 {
                        if shape.ShapeType == "bar" && shape.Style == "2color" {
                            drawTitles = append(drawTitles, shape.Title + " " + ToFixed(shape.Datas[crossLineIndex], inChart.VolDigit))
                            drawColors = append(drawColors, shape.Color2)
                        } else {
                            if shape.ShapeType != "text" {
                                drawTitles = append(drawTitles, shape.Title + " " + ToFixed(shape.Datas[crossLineIndex], inChart.VolDigit))
                                drawColors = append(drawColors, shape.Color)
                                if len(shape.Datas2) > 0 {
                                    drawTitles = append(drawTitles, shape.Title2 + " " + ToFixed(shape.Datas2[crossLineIndex], inChart.VolDigit))
                                    drawColors = append(drawColors, shape.Color2)
                                }
                            }
                        }
                    }
                }
            }
        }
        iLeft := inChart.LeftVScaleWidth + 5
        for i:= 0; i < len(drawTitles); i++ {
            tSize := paint.TextSize(drawTitles[i], chart.Font)
            paint.DrawText(drawTitles[i], drawColors[i], chart.Font, iLeft, candleDivHeight + 5)
            iLeft += tSize.Cx + 5
        }
    }
    //上面显示数据  高开低收
    if inChart.Cycle == "trend" {
        var drawTitles []string
        var drawColors []string
        if len(chart.Text) > 0{
            drawTitles = append(drawTitles, chart.Text)
            drawColors = append(drawColors, chart.TextColor)
        }
        drawTitles = append(drawTitles, "CLOSE " + ToFixed(inChart.Data[crossLineIndex].Close, inChart.CandleDigit))
        drawColors = append(drawColors, chart.TextColor)
        if len(inChart.Shapes) > 0 {
            for i:= 0; i < len(inChart.Shapes); i++ {
                shape := inChart.Shapes[i]
                if shape.DivIndex == 0 {
                    if len(shape.Title) > 0 {
                        if shape.ShapeType == "bar" && shape.Style == "2color" {
                            drawTitles = append(drawTitles, shape.Title + " " + ToFixed(shape.Datas[crossLineIndex], inChart.CandleDigit))
                            drawColors = append(drawColors, shape.Color2)
                        } else {
                            if shape.ShapeType != "text" {
                                drawTitles = append(drawTitles, shape.Title + " " + ToFixed(shape.Datas[crossLineIndex], inChart.CandleDigit))
                                drawColors = append(drawColors, shape.Color)
                                if len(shape.Datas2) > 0 {
                                    drawTitles = append(drawTitles, shape.Title2 + " " + ToFixed(shape.Datas2[crossLineIndex], inChart.CandleDigit))
                                    drawColors = append(drawColors, shape.Color2)
                                }
                            }
                        }
                    }
                }
            }
        }
        iLeft := inChart.LeftVScaleWidth + 5
        for i:= 0; i < len(drawTitles); i++ {
            tSize := paint.TextSize(drawTitles[i], chart.Font)
            paint.DrawText(drawTitles[i], drawColors[i], chart.Font, iLeft, 5)
            iLeft += tSize.Cx + 5
        }
    } else {
        var drawTitles []string
        var drawColors []string
        if len(chart.Text) > 0{
            drawTitles = append(drawTitles, chart.Text)
            drawColors = append(drawColors, chart.TextColor)
        }
        if inChart.MainIndicator == "MA" {
            if len(inChart.Ma5) > 0 {
                drawTitles = append(drawTitles, "MA5 " + ToFixed(inChart.Ma5[crossLineIndex], inChart.CandleDigit))
            } else {
                drawTitles = append(drawTitles, "MA5")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[0])
            if len(inChart.Ma10) > 0 {
                drawTitles = append(drawTitles, "MA10 " + ToFixed(inChart.Ma10[crossLineIndex], inChart.CandleDigit))
            } else {
                drawTitles = append(drawTitles, "MA10")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[1])
            if len(inChart.Ma20) > 0 {
                drawTitles = append(drawTitles, "MA20 " + ToFixed(inChart.Ma20[crossLineIndex], inChart.CandleDigit))

            } else {
                drawTitles = append(drawTitles, "MA20")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[2])
            if len(inChart.Ma30) > 0 {
                drawTitles = append(drawTitles, "MA30 " + ToFixed(inChart.Ma30[crossLineIndex], inChart.CandleDigit))
            } else {
                drawTitles = append(drawTitles, "MA30")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[5])
            if len(inChart.Ma120) > 0 {
                drawTitles = append(drawTitles, "MA120 " + ToFixed(inChart.Ma120[crossLineIndex], inChart.CandleDigit))

            } else {
                drawTitles = append(drawTitles, "MA120")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[4])
            if len(inChart.Ma250) > 0 {
                drawTitles = append(drawTitles, "MA250 " + ToFixed(inChart.Ma250[crossLineIndex], inChart.CandleDigit))
            } else {
                drawTitles = append(drawTitles, "MA250")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[3])
        } else if inChart.MainIndicator == "BOLL" {
            if len(inChart.BollMid) > 0 {
                drawTitles = append(drawTitles, "MID " + ToFixed(inChart.BollMid[crossLineIndex], inChart.CandleDigit))
            } else {
                drawTitles = append(drawTitles, "MID")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[0])
            if len(inChart.BollUp) > 0 {
                drawTitles = append(drawTitles, "UP " + ToFixed(inChart.BollUp[crossLineIndex], inChart.CandleDigit))
            } else {
                drawTitles = append(drawTitles, "UP")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[1])
            if len(inChart.BollDown) > 0 {
                drawTitles = append(drawTitles, "LOW " + ToFixed(inChart.BollDown[crossLineIndex], inChart.CandleDigit))
            } else {
                drawTitles = append(drawTitles, "LOW")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[2])
        }
        if len(inChart.Shapes) > 0 {
            for i:= 0; i < len(inChart.Shapes); i++ {
                shape := inChart.Shapes[i]
                if shape.DivIndex == 0 {
                    if len(shape.Title) > 0 {
                        if shape.ShapeType == "bar" && shape.Style == "2color" {
                            drawTitles = append(drawTitles, shape.Title + " " + ToFixed(shape.Datas[crossLineIndex], inChart.CandleDigit))
                            drawColors = append(drawColors, shape.Color2)
                        } else {
                            if shape.ShapeType != "text" {
                                drawTitles = append(drawTitles, shape.Title + " " + ToFixed(shape.Datas[crossLineIndex], inChart.CandleDigit))
                                drawColors = append(drawColors, shape.Color)
                                if len(shape.Datas2) > 0 {
                                    drawTitles = append(drawTitles, shape.Title2 + " " + ToFixed(shape.Datas2[crossLineIndex], inChart.CandleDigit))
                                    drawColors = append(drawColors, shape.Color2)
                                }
                            }
                        }
                    }
                }
            }
        }
        iLeft := inChart.LeftVScaleWidth + 5
        for i:= 0; i < len(drawTitles); i++ {
            tSize := paint.TextSize(drawTitles[i], chart.Font)
            paint.DrawText(drawTitles[i], drawColors[i], chart.Font, iLeft, 5)
            iLeft += tSize.Cx + 5
        }
    }
    if indDivHeight > 0 {
        var drawTitles []string
        var drawColors []string
        if inChart.ShowIndicator == "MACD" {
            if len(inChart.Alldifarr) > 0 {
                drawTitles = append(drawTitles, "DIF " + ToFixed(inChart.Alldifarr[crossLineIndex], inChart.IndDigit))
            } else {
                drawTitles = append(drawTitles, "DIF")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[0])
            if len(inChart.Alldeaarr) > 0 {
                drawTitles = append(drawTitles, "DEA " + ToFixed(inChart.Alldeaarr[crossLineIndex], inChart.IndDigit))
            } else {
                drawTitles = append(drawTitles, "DEA")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[1])
            if len(inChart.Allmacdarr) > 0 {
                drawTitles = append(drawTitles, "MACD " + ToFixed(inChart.Allmacdarr[crossLineIndex], inChart.IndDigit))
            } else {
                drawTitles = append(drawTitles, "MACD")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[4])
        } else if inChart.ShowIndicator == "KDJ" {
            if len(inChart.KdjK) > 0 {
                drawTitles = append(drawTitles, "K " + ToFixed(inChart.KdjK[crossLineIndex], inChart.IndDigit))
            } else {
                drawTitles = append(drawTitles, "K")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[0])
            if len(inChart.KdjD) > 0 {
                drawTitles = append(drawTitles, "D " + ToFixed(inChart.KdjD[crossLineIndex], inChart.IndDigit))
            } else {
                drawTitles = append(drawTitles, "D")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[1])
            if len(inChart.KdjJ) > 0 {
                drawTitles = append(drawTitles, "J " + ToFixed(inChart.KdjJ[crossLineIndex], inChart.IndDigit))
            } else {
                drawTitles = append(drawTitles, "J")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[2])
        } else if inChart.ShowIndicator == "RSI" {
            if len(inChart.Rsi1) > 0 {
                drawTitles = append(drawTitles, "RSI6 " + ToFixed(inChart.Rsi1[crossLineIndex], inChart.IndDigit))
            } else {
                drawTitles = append(drawTitles, "RSI6")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[5])
            if len(inChart.Rsi2) > 0 {
                drawTitles = append(drawTitles, "RSI12 " + ToFixed(inChart.Rsi2[crossLineIndex], inChart.IndDigit))
            } else {
                drawTitles = append(drawTitles, "RSI12")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[1])
            if (len(inChart.Rsi3) > 0) {
                drawTitles = append(drawTitles, "RSI24 " + ToFixed(inChart.Rsi3[crossLineIndex], inChart.IndDigit))
            } else {
                drawTitles = append(drawTitles, "RSI24")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[2])
        }else if (inChart.ShowIndicator == "BIAS") {
            if len(inChart.Bias1) > 0{
                drawTitles = append(drawTitles, "BIAS6 " + ToFixed(inChart.Bias1[crossLineIndex], inChart.IndDigit))
            } else {
                drawTitles = append(drawTitles, "BIAS6")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[5])
            if len(inChart.Bias2) > 0 {
                drawTitles = append(drawTitles, "BIAS12 " + ToFixed(inChart.Bias2[crossLineIndex], inChart.IndDigit))
            } else {
                drawTitles = append(drawTitles, "BIAS12")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[1])
            if len(inChart.Bias3) > 0 {
                drawTitles = append(drawTitles, "BIAS24 " + ToFixed(inChart.Bias3[crossLineIndex], inChart.IndDigit))
            } else {
                drawTitles = append(drawTitles, "BIAS24")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[2])
        } else if inChart.ShowIndicator == "ROC" {
            if len(inChart.Roc) > 0 {
                drawTitles = append(drawTitles, "ROC " + ToFixed(inChart.Roc[crossLineIndex], inChart.IndDigit))
            } else {
                drawTitles = append(drawTitles, "ROC")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[0])
            if len(inChart.RocMa) > 0 {
                drawTitles = append(drawTitles, "ROCMA " + ToFixed(inChart.RocMa[crossLineIndex], inChart.IndDigit))
            } else {
                drawTitles = append(drawTitles, "ROCMA")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[1])
        }else if inChart.ShowIndicator == "WR" {
            if len(inChart.Wr1) > 0 {
                drawTitles = append(drawTitles, "WR5 " + ToFixed(inChart.Wr1[crossLineIndex], inChart.IndDigit))
            } else {
                drawTitles = append(drawTitles, "WR5")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[0])
            if len(inChart.Wr2) > 0 {
                drawTitles = append(drawTitles, "WR10 " + ToFixed(inChart.Wr2[crossLineIndex], inChart.IndDigit))
            } else {
                drawTitles = append(drawTitles, "WR10")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[1])
        } else if inChart.ShowIndicator == "CCI" {
            if len(inChart.Cci) > 0 {
                drawTitles = append(drawTitles, "CCI " + ToFixed(inChart.Cci[crossLineIndex], inChart.IndDigit))
            } else {
                drawTitles = append(drawTitles, "CCI")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[0])
        } else if inChart.ShowIndicator == "BBI" {
            if len(inChart.Bbi) > 0 {
                drawTitles = append(drawTitles, "BBI " + ToFixed(inChart.Bbi[crossLineIndex], inChart.IndDigit))
            } else {
                drawTitles = append(drawTitles, "BBI")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[0])
        } else if inChart.ShowIndicator == "TRIX" {
            if len(inChart.Trix) > 0 {
                drawTitles = append(drawTitles, "TRIX " + ToFixed(inChart.Trix[crossLineIndex], inChart.IndDigit))
            } else {
                drawTitles = append(drawTitles, "TRIX")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[0])
            if len(inChart.TrixMa) > 0 {
                drawTitles = append(drawTitles, "TRIXMA " + ToFixed(inChart.TrixMa[crossLineIndex], inChart.IndDigit))
            } else {
                drawTitles = append(drawTitles, "TRIXMA")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[1])
        } else if inChart.ShowIndicator == "DMA" {
            if len(inChart.Dma1) > 0 {
                drawTitles = append(drawTitles, "MA10 " + ToFixed(inChart.Dma1[crossLineIndex], inChart.IndDigit))
            } else {
                drawTitles = append(drawTitles, "MA10")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[0])
            if len(inChart.Dma2) > 0 {
                drawTitles = append(drawTitles, "MA50 " + ToFixed(inChart.Dma2[crossLineIndex], inChart.IndDigit))
            } else {
                drawTitles = append(drawTitles, "MA50")
            }
            drawColors = append(drawColors, inChart.IndicatorColors[1])
        }
        if len(inChart.Shapes) > 0 {
            for i:= 0; i < len(inChart.Shapes); i++ {
                shape := inChart.Shapes[i]
                if shape.DivIndex == 2 {
                    if len(shape.Title) > 0 {
                        if shape.ShapeType == "bar" && shape.Style == "2color" {
                            drawTitles = append(drawTitles, shape.Title + " " + ToFixed(shape.Datas[crossLineIndex], inChart.IndDigit))
                            drawColors = append(drawColors, shape.Color2)
                        } else {
                            if shape.ShapeType != "text" {
                                drawTitles = append(drawTitles, shape.Title + " " + ToFixed(shape.Datas[crossLineIndex], inChart.IndDigit))
                                drawColors = append(drawColors, shape.Color)
                                if len(shape.Datas2) > 0 {
                                    drawTitles = append(drawTitles, shape.Title2 + " " + ToFixed(shape.Datas2[crossLineIndex], inChart.IndDigit))
                                    drawColors = append(drawColors, shape.Color2)
                                }
                            }
                        }
                    }
                }
            }
        }
        iLeft := inChart.LeftVScaleWidth + 5
        for i:= 0; i < len(drawTitles); i++ {
            tSize := paint.TextSize(drawTitles[i], chart.Font)
            paint.DrawText(drawTitles[i], drawColors[i], chart.Font, iLeft, candleDivHeight + volDivHeight + 5)
            iLeft += tSize.Cx + 5
        }
    }
    if indDivHeight2 > 0 {
        var drawTitles []string
        var drawColors []string
        if len(inChart.Shapes) > 0 {
            for i:= 0; i < len(inChart.Shapes); i++ {
                shape := inChart.Shapes[i]
                if shape.DivIndex == 3 {
                    if len(shape.Title) > 0 {
                        if shape.ShapeType == "bar" && shape.Style == "2color" {
                            drawTitles = append(drawTitles, shape.Title + " " + ToFixed(shape.Datas[crossLineIndex], inChart.IndDigit2))
                            drawColors = append(drawColors, shape.Color2)
                        } else {
                            if shape.ShapeType != "text" {
                                drawTitles = append(drawTitles, shape.Title + " " + ToFixed(shape.Datas[crossLineIndex], inChart.IndDigit2))
                                drawColors = append(drawColors, shape.Color)
                                if len(shape.Datas2) > 0 {
                                    drawTitles = append(drawTitles, shape.Title2 + " " + ToFixed(shape.Datas2[crossLineIndex], inChart.IndDigit2))
                                    drawColors = append(drawColors, shape.Color2)
                                }
                            }
                        }
                    }
                }
            }
        }
        if len(drawTitles) > 0 {
            iLeft := inChart.LeftVScaleWidth + 5
            for i:= 0; i < len(drawTitles); i++ {
                tSize := paint.TextSize(drawTitles[i], chart.Font)
                paint.DrawText(drawTitles[i], drawColors[i], chart.Font, iLeft, candleDivHeight + volDivHeight + indDivHeight + 5 + tSize.Cy / 2)
                iLeft += tSize.Cx + 5
            }
        }
    }

    if inChart.ShowCrossLine {
        rightText := ""
        if inChart.TouchPosition.Y < candleDivHeight {
            rightText = ToFixed(GetChartValue(chart, inChart.TouchPosition), inChart.CandleDigit)
        }else if inChart.TouchPosition.Y > candleDivHeight && inChart.TouchPosition.Y < candleDivHeight + volDivHeight {
            rightText = ToFixed(GetChartValue(chart, inChart.TouchPosition) / float64(inChart.Magnitude), inChart.VolDigit)
        } else if inChart.TouchPosition.Y > candleDivHeight + volDivHeight && inChart.TouchPosition.Y < candleDivHeight + volDivHeight + indDivHeight {
            rightText = ToFixed(GetChartValue(chart, inChart.TouchPosition), inChart.IndDigit)
        } else if inChart.TouchPosition.Y > candleDivHeight + volDivHeight + indDivHeight && inChart.TouchPosition.Y < candleDivHeight + volDivHeight + indDivHeight + indDivHeight2 {
            rightText = ToFixed(GetChartValue(chart, inChart.TouchPosition), inChart.IndDigit2)
        }

        drawY := inChart.TouchPosition.Y
        if drawY > chart.Size.Cy - inChart.HScaleHeight {
            drawY = chart.Size.Cy - inChart.HScaleHeight
        }
        tSize := paint.TextSize(rightText, chart.Font)
        if inChart.LeftVScaleWidth > 0{
            paint.FillRect(inChart.CrossTipColor, inChart.LeftVScaleWidth - tSize.Cx, drawY - tSize.Cy / 2 - 4, inChart.LeftVScaleWidth, drawY + tSize.Cy / 2 + 3)
            paint.DrawText(rightText, chart.TextColor, chart.Font, inChart.LeftVScaleWidth - tSize.Cx, drawY - tSize.Cy / 2)
        }
        if inChart.RightVScaleWidth > 0 {
            paint.FillRect(inChart.CrossTipColor, chart.Size.Cx - inChart.RightVScaleWidth, drawY - tSize.Cy / 2 - 4, chart.Size.Cx - inChart.RightVScaleWidth + tSize.Cx, drawY + tSize.Cy / 2 + 3)
            paint.DrawText(rightText, chart.TextColor, chart.Font, chart.Size.Cx - inChart.RightVScaleWidth, drawY - tSize.Cy / 2)
        }
        //绘制十字线
        drawX := GetChartX(chart, inChart.CrossStopIndex)
		if inChart.TargetOldX == 0 && inChart.TargetOldX2 == 0{
			drawX = inChart.TouchPosition.X
		}
        if drawX < inChart.LeftVScaleWidth {
            drawX = inChart.LeftVScaleWidth
        }
        if drawX > chart.Size.Cx - inChart.RightVScaleWidth {
            drawX = chart.Size.Cx - inChart.RightVScaleWidth
        }
        sPlot := inChart.GetSelectedPlot()
        if !sPlot.IsNotEmpty && inChart.SelectShape == "" {
            paint.DrawLine(inChart.CrossLineColor, inChart.LineWidthChart, 0, inChart.LeftVScaleWidth, drawY, chart.Size.Cx - inChart.RightVScaleWidth, drawY)
            paint.DrawLine(inChart.CrossLineColor, inChart.LineWidthChart, 0, drawX, 0, drawX, chart.Size.Cy - inChart.HScaleHeight)
        }
        if inChart.CrossStopIndex != -1 {
            tm := time.Unix(int64(inChart.Data[inChart.CrossStopIndex].Date / 1000), 0)
            xText := ""
            if len(inChart.HScaleFormat) > 0{
                xText = tm.Format(inChart.HScaleFormat)
			} else {
				if inChart.Cycle == "day" {
					xText = tm.Format("2006-01-02")
				} else if inChart.Cycle == "minute" {
					xText = tm.Format("2006/01/02 15:04")
				} else if inChart.Cycle == "trend" {
					xText = tm.Format("15:04")
				}else if inChart.Cycle == "second" {
					xText = tm.Format("15:04:05")
				}else if inChart.Cycle == "tick" {
					xText = ConvertIntToStr(inChart.CrossStopIndex + 1)
				}
			}
            xSize := paint.TextSize(xText, chart.Font)
            paint.FillRect(inChart.CrossTipColor, drawX - xSize.Cx / 2 - 2, candleDivHeight + volDivHeight + indDivHeight, drawX + xSize.Cx / 2 + 2, candleDivHeight + volDivHeight + indDivHeight + xSize.Cy + 6)
            paint.DrawText(xText, chart.TextColor, chart.Font, drawX - xSize.Cx / 2, candleDivHeight + volDivHeight + indDivHeight + 3)
        }
    }
}

/*
* 计算最大最小值
* chart:图表
*/
func CalculateChartMaxMin(chart *FCView) {
    inChart := chart.GetChart()
    inChart.CandleMax = 0
    inChart.CandleMin = 0
    inChart.VolMax = 0
    inChart.VolMin = 0
    inChart.IndMin = 0
    inChart.IndMin = 0
    load1 := false
    load2 := false
    load3 := false
    load4 := false
    isTrend := false
    if inChart.Cycle == "trend"{
        isTrend = true
    }
    firstOpen := inChart.FirstOpen
    if len(inChart.Data) > 0 {
        lastValidIndex := inChart.LastVisibleIndex
        if inChart.LastValidIndex != -1 {
            lastValidIndex = inChart.LastValidIndex
        }
        for i := inChart.FirstVisibleIndex; i <= lastValidIndex; i++ {
            if i == inChart.FirstVisibleIndex {
                if isTrend {
                    inChart.CandleMax = inChart.Data[i].Close
                    inChart.CandleMin = inChart.Data[i].Close
                    if firstOpen == 0{
                        firstOpen = inChart.Data[i].Close
                    }
                } else {
                    inChart.CandleMax = inChart.Data[i].High
                    inChart.CandleMin = inChart.Data[i].Low
                }
                inChart.VolMax = inChart.Data[i].Volume
                load1 = true
                load2 = true
                if inChart.ShowIndicator == "MACD" {
                    inChart.IndMax = inChart.Alldifarr[i]
                    inChart.IndMin = inChart.Alldifarr[i]
                    load3 = true
                }else if inChart.ShowIndicator == "KDJ" {
                    inChart.IndMax = inChart.KdjK[i]
                    inChart.IndMin = inChart.KdjK[i]
                    load3 = true
                }else if inChart.ShowIndicator == "RSI" {
                    inChart.IndMax = inChart.Rsi1[i]
                    inChart.IndMin = inChart.Rsi1[i]
                    load3 = true
                }else if inChart.ShowIndicator == "BIAS" {
                    inChart.IndMax = inChart.Bias1[i]
                    inChart.IndMin = inChart.Bias1[i]
                    load3 = true
                }else if inChart.ShowIndicator == "ROC" {
                    inChart.IndMax = inChart.Roc[i]
                    inChart.IndMin = inChart.Roc[i]
                    load3 = true
                }else if inChart.ShowIndicator == "WR" {
                    inChart.IndMax = inChart.Wr1[i]
                    inChart.IndMin = inChart.Wr1[i]
                    load3 = true
                } else if inChart.ShowIndicator == "CCI" {
                    inChart.IndMax = inChart.Cci[i]
                    inChart.IndMin = inChart.Cci[i]
                    load3 = true
                } else if inChart.ShowIndicator == "BBI" {
                    inChart.IndMax = inChart.Bbi[i]
                    inChart.IndMin = inChart.Bbi[i]
                    load3 = true
                }else if inChart.ShowIndicator == "TRIX" {
                    inChart.IndMax = inChart.Trix[i]
                    inChart.IndMin = inChart.Trix[i]
                    load3 = true
                }else if inChart.ShowIndicator == "DMA" {
                    inChart.IndMax = inChart.Dma1[i]
                    inChart.IndMin = inChart.Dma1[i]
                    load3 = true
                }
            }else {
                if isTrend{
                    if inChart.CandleMax < inChart.Data[i].Close {
                        inChart.CandleMax = inChart.Data[i].Close
                    }
                    if inChart.CandleMin > inChart.Data[i].Close{
                        inChart.CandleMin = inChart.Data[i].Close
                    }
                } else {
                    if inChart.CandleMax < inChart.Data[i].High {
                        inChart.CandleMax = inChart.Data[i].High
                    }
                    if inChart.CandleMin > inChart.Data[i].Low{
                        inChart.CandleMin = inChart.Data[i].Low
                    }
                }
                if inChart.VolMax < inChart.Data[i].Volume {
                    inChart.VolMax = inChart.Data[i].Volume
                }
            }
            if inChart.ShowIndicator == "MACD" {
                if inChart.IndMax < inChart.Alldifarr[i] {
                    inChart.IndMax = inChart.Alldifarr[i]
                }
                if inChart.IndMax < inChart.Alldeaarr[i] {
                    inChart.IndMax = inChart.Alldeaarr[i]
                }
                if inChart.IndMax < inChart.Allmacdarr[i] {
                    inChart.IndMax = inChart.Allmacdarr[i]
                }
                if inChart.IndMin > inChart.Alldifarr[i] {
                    inChart.IndMin = inChart.Alldifarr[i]
                }
                if inChart.IndMin > inChart.Alldeaarr[i] {
                    inChart.IndMin = inChart.Alldeaarr[i]
                }
                if inChart.IndMin > inChart.Allmacdarr[i] {
                    inChart.IndMin = inChart.Allmacdarr[i]
                }
            } else if inChart.ShowIndicator == "KDJ" {
                if inChart.IndMax < inChart.KdjK[i] {
                    inChart.IndMax = inChart.KdjK[i]
                }
                if inChart.IndMax < inChart.KdjD[i] {
                    inChart.IndMax = inChart.KdjD[i]
                }
                if inChart.IndMax < inChart.KdjJ[i] {
                    inChart.IndMax = inChart.KdjJ[i]
                }
                if inChart.IndMin > inChart.KdjK[i] {
                    inChart.IndMin = inChart.KdjK[i]
                }
                if inChart.IndMin > inChart.KdjD[i] {
                    inChart.IndMin = inChart.KdjD[i]
                }
                if inChart.IndMin > inChart.KdjJ[i] {
                    inChart.IndMin = inChart.KdjJ[i]
                }
            } else if inChart.ShowIndicator == "RSI" {
                if inChart.IndMax < inChart.Rsi1[i] {
                    inChart.IndMax = inChart.Rsi1[i]
                }
                if inChart.IndMax < inChart.Rsi2[i] {
                    inChart.IndMax = inChart.Rsi2[i]
                }
                if inChart.IndMax < inChart.Rsi3[i] {
                    inChart.IndMax = inChart.Rsi3[i]
                }
                if inChart.IndMin > inChart.Rsi1[i] {
                    inChart.IndMin = inChart.Rsi1[i]
                }
                if inChart.IndMin > inChart.Rsi2[i] {
                    inChart.IndMin = inChart.Rsi2[i]
                }
                if inChart.IndMin > inChart.Rsi3[i] {
                    inChart.IndMin = inChart.Rsi3[i]
                }
            } else if inChart.ShowIndicator == "BIAS" {
                if inChart.IndMax < inChart.Bias1[i]{
                    inChart.IndMax = inChart.Bias1[i]
                }
                if inChart.IndMax < inChart.Bias2[i] {
                    inChart.IndMax = inChart.Bias2[i]
                }
                if inChart.IndMax < inChart.Bias3[i] {
                    inChart.IndMax = inChart.Bias3[i]
                }
                if inChart.IndMin > inChart.Bias1[i] {
                    inChart.IndMin = inChart.Bias1[i]
                }
                if inChart.IndMin > inChart.Bias2[i] {
                    inChart.IndMin = inChart.Bias2[i]
                }
                if inChart.IndMin > inChart.Bias3[i] {
                    inChart.IndMin = inChart.Bias3[i]
                }
            } else if inChart.ShowIndicator == "ROC" {
                if inChart.IndMax < inChart.Roc[i]{
                    inChart.IndMax = inChart.Roc[i]
                }
                if inChart.IndMax < inChart.RocMa[i] {
                    inChart.IndMax = inChart.RocMa[i]
                }
                if inChart.IndMin > inChart.Roc[i] {
                    inChart.IndMin = inChart.Roc[i]
                }
                if inChart.IndMin > inChart.RocMa[i] {
                    inChart.IndMin = inChart.RocMa[i]
                }
            }else if inChart.ShowIndicator == "WR" {
                if inChart.IndMax < inChart.Wr1[i] {
                    inChart.IndMax = inChart.Wr1[i]
                }
                if inChart.IndMax < inChart.Wr2[i] {
                    inChart.IndMax = inChart.Wr2[i]
                }
                if inChart.IndMin > inChart.Wr1[i] {
                    inChart.IndMin = inChart.Wr1[i]
                }
                if inChart.IndMin > inChart.Wr2[i] {
                    inChart.IndMin = inChart.Wr2[i]
                }
            } else if inChart.ShowIndicator == "CCI" {
                if inChart.IndMax < inChart.Cci[i] {
                    inChart.IndMax = inChart.Cci[i]
                }
                if inChart.IndMin > inChart.Cci[i] {
                    inChart.IndMin = inChart.Cci[i]
                }
            } else if inChart.ShowIndicator == "BBI" {
                if inChart.IndMax < inChart.Bbi[i] {
                    inChart.IndMax = inChart.Bbi[i]
                }
                if inChart.IndMin > inChart.Bbi[i] {
                    inChart.IndMin = inChart.Bbi[i]
                }
            } else if inChart.ShowIndicator == "TRIX" {
                if inChart.IndMax < inChart.Trix[i] {
                    inChart.IndMax = inChart.Trix[i]
                }
                if inChart.IndMax < inChart.TrixMa[i] {
                    inChart.IndMax = inChart.TrixMa[i]
                }
                if inChart.IndMin > inChart.Trix[i]{
                    inChart.IndMin = inChart.Trix[i]
                }
                if inChart.IndMin > inChart.TrixMa[i]{
                    inChart.IndMin = inChart.TrixMa[i]
                }
            } else if inChart.ShowIndicator == "DMA" {
                if inChart.IndMax < inChart.Dma1[i] {
                    inChart.IndMax = inChart.Dma1[i]
                }
                if inChart.IndMax < inChart.Dma2[i] {
                    inChart.IndMax = inChart.Dma2[i]
                }
                if inChart.IndMin > inChart.Dma1[i] {
                    inChart.IndMin = inChart.Dma1[i]
                }
                if inChart.IndMin > inChart.Dma2[i]{
                    inChart.IndMin = inChart.Dma2[i]
                }
            }
        }
    }
    if len(inChart.Shapes) > 0 {
        lastValidIndex := inChart.LastVisibleIndex
        if inChart.LastValidIndex != -1 {
            lastValidIndex = inChart.LastValidIndex
        }
        for s := 0; s <= len(inChart.Shapes); s++ {
            shape := inChart.Shapes[s]
            if len(shape.Datas) > 0{
                for i := inChart.FirstVisibleIndex; i <= lastValidIndex; i++ {
                    if shape.DivIndex == 0 {
                        if !load1 && i == inChart.FirstVisibleIndex {
                            if shape.LeftOrRight {
                                inChart.CandleMax = shape.Datas[i]
                                inChart.CandleMin = shape.Datas[i]
                            } else {
                                inChart.CandleMaxRight = shape.Datas[i]
                                inChart.CandleMinRight = shape.Datas[i]
                            }
                            load1 = true
                        } else {
                            if shape.LeftOrRight {
                                if shape.Datas[i] > inChart.CandleMax {
                                    inChart.CandleMax = shape.Datas[i]
                                }
                                if shape.Datas[i] < inChart.CandleMin {
                                    inChart.CandleMin = shape.Datas[i]
                                }
                            } else {
                                if shape.Datas[i] > inChart.CandleMaxRight {
                                    inChart.CandleMaxRight = shape.Datas[i]
                                }
                                if shape.Datas[i] < inChart.CandleMinRight {
                                    inChart.CandleMinRight = shape.Datas[i]
                                }
                            }
                        }
                    } else if shape.DivIndex == 1 {
                        if !load2 && i == inChart.FirstVisibleIndex {
                            if shape.LeftOrRight{
                                inChart.VolMax = shape.Datas[i]
                                inChart.VolMin = shape.Datas[i]
                            } else {
                                inChart.VolMaxRight = shape.Datas[i]
                                inChart.VolMinRight = shape.Datas[i]
                            }
                            load2 = true
                        } else {
                            if shape.LeftOrRight {
                                if shape.Datas[i] > inChart.VolMax {
                                    inChart.VolMax = shape.Datas[i]
                                }
                                if shape.Datas[i] < inChart.VolMin {
                                    inChart.VolMin = shape.Datas[i]
                                }
                            } else {
                                if shape.Datas[i] > inChart.VolMaxRight {
                                    inChart.VolMaxRight = shape.Datas[i]
                                }
                                if shape.Datas[i] < inChart.VolMinRight {
                                    inChart.VolMinRight = shape.Datas[i]
                                }
                            }
                        }
                    } else if shape.DivIndex == 2 {
                        if !load3 && i == inChart.FirstVisibleIndex {
                            if shape.LeftOrRight {
                                inChart.IndMax = shape.Datas[i]
                                inChart.IndMin = shape.Datas[i]
                            } else {
                                inChart.IndMaxRight = shape.Datas[i]
                                inChart.IndMinRight = shape.Datas[i]
                            }
                            load3 = true
                        } else {
                            if shape.LeftOrRight {
                                if shape.Datas[i] > inChart.IndMax {
                                    inChart.IndMax = shape.Datas[i]
                                }
                                if shape.Datas[i] < inChart.IndMin {
                                    inChart.IndMin = shape.Datas[i]
                                }
                            } else {
                                if shape.Datas[i] > inChart.IndMaxRight {
                                    inChart.IndMaxRight = shape.Datas[i]
                                }
                                if shape.Datas[i] < inChart.IndMinRight {
                                    inChart.IndMinRight = shape.Datas[i]
                                }
                            }
                        }
                    } else if shape.DivIndex == 3 {
                        if !load4 && i == inChart.FirstVisibleIndex {
                            if shape.LeftOrRight {
                                inChart.IndMax2 = shape.Datas[i]
                                inChart.IndMin2 = shape.Datas[i]
                            } else {
                                inChart.IndMax2Right = shape.Datas[i]
                                inChart.IndMin2Right = shape.Datas[i]
                            }
                            load4 = true
                        } else {
                            if shape.LeftOrRight {
                                if shape.Datas[i] > inChart.IndMax2 {
                                    inChart.IndMax2 = shape.Datas[i]
                                }
                                if shape.Datas[i] < inChart.IndMin2 {
                                    inChart.IndMin2 = shape.Datas[i]
                                }
                            } else {
                                if shape.Datas[i] > inChart.IndMax2Right {
                                    inChart.IndMax2Right = shape.Datas[i]
                                }
                                if shape.Datas[i] < inChart.IndMin2Right {
                                    inChart.IndMin2Right = shape.Datas[i]
                                }
                            }
                        }
                    }
                }
            }
            if len(shape.Datas2) > 0 {
                for i := inChart.FirstVisibleIndex; i <= lastValidIndex; i++ {
                    if shape.DivIndex == 0 {
                        if shape.LeftOrRight {
                            if shape.Datas2[i] > inChart.CandleMax {
                                inChart.CandleMax = shape.Datas2[i]
                            }
                            if shape.Datas2[i] < inChart.CandleMin {
                                inChart.CandleMin = shape.Datas2[i]
                            }
                        } else {
                            if shape.Datas2[i] > inChart.CandleMaxRight {
                                inChart.CandleMaxRight = shape.Datas2[i]
                            }
                            if shape.Datas2[i] < inChart.CandleMinRight{
                                inChart.CandleMinRight = shape.Datas2[i]
                            }
                        }
                    } else if shape.DivIndex == 1 {
                        if shape.LeftOrRight {
                            if shape.Datas2[i] > inChart.VolMax {
                                inChart.VolMax = shape.Datas2[i]
                            }
                            if shape.Datas2[i] < inChart.VolMin {
                                inChart.VolMin = shape.Datas2[i]
                            }
                        } else {
                            if shape.Datas2[i] > inChart.VolMaxRight {
                                inChart.VolMaxRight = shape.Datas2[i]
                            }
                            if shape.Datas2[i] < inChart.VolMinRight {
                                inChart.VolMinRight = shape.Datas2[i]
                            }
                        }
                    } else if shape.DivIndex == 2 {
                        if shape.LeftOrRight {
                            if shape.Datas2[i] > inChart.IndMax {
                                inChart.IndMax = shape.Datas2[i]
                            }
                            if shape.Datas2[i] < inChart.IndMin {
                                inChart.IndMin = shape.Datas2[i]
                            }
                        } else {
                            if shape.Datas2[i] > inChart.IndMaxRight {
                                inChart.IndMaxRight = shape.Datas2[i]
                            }
                            if shape.Datas2[i] < inChart.IndMinRight {
                                inChart.IndMinRight = shape.Datas2[i]
                            }
                        }
                    } else if shape.DivIndex == 3 {
                        if shape.LeftOrRight {
                            if shape.Datas2[i] > inChart.IndMax2 {
                                inChart.IndMax2 = shape.Datas2[i]
                            }
                            if shape.Datas2[i] < inChart.IndMin2 {
                                inChart.IndMin2 = shape.Datas2[i]
                            }
                        } else {
                            if shape.Datas2[i] > inChart.IndMax2Right {
                                inChart.IndMax2Right = shape.Datas2[i]
                            }
                            if shape.Datas2[i] < inChart.IndMin2Right {
                                inChart.IndMin2Right = shape.Datas2[i]
                            }
                        }
                    }
                }
            }
        }
    }
    if isTrend {
        subMax := math.Max(math.Abs(inChart.CandleMax - firstOpen), math.Abs(inChart.CandleMin - firstOpen))
        inChart.CandleMax = firstOpen + subMax
        inChart.CandleMin = firstOpen - subMax
    } else {
        if inChart.CandleMax == 0 && inChart.CandleMin == 0 {
            inChart.CandleMax = 1
            inChart.CandleMin = -1
        }
        if inChart.VolMax == 0 && inChart.VolMin == 0 {
            inChart.VolMax = 1
            inChart.VolMin = -1
        }
        if inChart.IndMax == 0 && inChart.IndMin == 0 {
            inChart.IndMax = 1
            inChart.IndMin = -1
        }
        if inChart.IndMax2 == 0 && inChart.IndMin2 == 0 {
            inChart.IndMax2 = 1
            inChart.IndMin2 = -1
        }
        if inChart.CandleMaxRight == 0 && inChart.CandleMinRight == 0 {
            inChart.CandleMaxRight = 1
            inChart.CandleMinRight = -1
        }
        if inChart.VolMaxRight == 0 && inChart.VolMinRight == 0 {
            inChart.VolMaxRight = 1
            inChart.VolMinRight = -1
        }
        if inChart.IndMaxRight == 0 && inChart.IndMinRight == 0 {
            inChart.IndMaxRight = 1
            inChart.IndMinRight = -1
        }
        if inChart.IndMax2Right == 0 && inChart.IndMin2Right == 0 {
            inChart.IndMax2Right = 1
            inChart.IndMin2Right = -1
        }
    }
}

/*
* 绘制线条
* chart:图表
* paint:绘图对象
* clipRect:裁剪区域
* divIndex:图层
* datas:数据
* color:颜色
* selected:是否选中
*/
func DrawChartLines(chart *FCView, paint *FCPaint, clipRect FCRect, divIndex int, datas []float64, color string, selected bool) {
    inChart := chart.GetChart()
    maxVisibleRecord := GetChartMaxVisibleCount(chart, inChart.HScalePixel, GetChartWorkAreaWidth(chart))
    lastValidIndex := inChart.LastVisibleIndex
    if inChart.LastValidIndex != -1 {
        lastValidIndex = inChart.LastValidIndex
    }
    var drawPoints []FCPoint
    for i := inChart.FirstVisibleIndex; i <= lastValidIndex; i++ {
        x := GetChartX(chart, i)
        value := datas[i]
        y := GetChartY(chart, divIndex, value)
        drawPoints = append(drawPoints, CreatePoint(x, y))
        if selected {
            kPInterval := int(maxVisibleRecord / 30)
            if kPInterval < 2 {
                kPInterval = 3
            }
            if i % kPInterval == 0 {
                paint.FillRect(color, x - 3, y - 3, x + 3, y + 3)
            }
        }
    }
    paint.DrawPolyline(color, inChart.LineWidthChart, 0, drawPoints)
}

/*
* 绘制线条到右轴
* chart:图表
* paint:绘图对象
* clipRect:裁剪区域
* divIndex:图层
* datas:数据
* color:颜色
* selected:是否选中
*/
func DrawChartLinesInRight(chart *FCView, paint *FCPaint, clipRect FCRect, divIndex int, datas []float64, color string, selected bool) {
    inChart := chart.GetChart()
    maxVisibleRecord := GetChartMaxVisibleCount(chart, inChart.HScalePixel, GetChartWorkAreaWidth(chart))
    lastValidIndex := inChart.LastVisibleIndex
    if inChart.LastValidIndex != -1 {
        lastValidIndex = inChart.LastValidIndex
    }
    var drawPoints []FCPoint
    for i := inChart.FirstVisibleIndex; i <= lastValidIndex; i++ {
        x := GetChartX(chart, i)
        value := datas[i]
        y := GetChartYInRight(chart, divIndex, value)
        drawPoints = append(drawPoints, CreatePoint(x, y))
        if selected {
            kPInterval := int(maxVisibleRecord / 30)
            if kPInterval < 2 {
                kPInterval = 3
            }
            if i % kPInterval == 0 {
                paint.FillRect(color, x - 3, y - 3, x + 3, y + 3)
            }
        }
    }
    paint.DrawPolyline(color, inChart.LineWidthChart, 0, drawPoints)
}

/*
* 绘制画线工具
* chart:图表
* paint:绘图对象
* clipRect:裁剪区域
*/
func DrawChartPlot(chart *FCView, paint *FCPaint, clipRect FCRect) {
    inChart := chart.GetChart()
    if len(inChart.Plots) > 0{
        divHeight := GetCandleDivHeight(chart)
        paint.Save()
        paint.SetClip(inChart.LeftVScaleWidth, 0, chart.Size.Cx - inChart.RightVScaleWidth, divHeight)
        for i := 0; i < len(inChart.Plots); i++ {
            plot := inChart.Plots[i]
            index1 := 0
            index2 := 0
            index3 := 0
            mpx1 := 0.0
            mpy1 := 0.0
            mpx2 := 0.0
            mpy2 := 0.0
            mpx3 := 0.0
            mpy3 := 0.0
            if plot.PlotType == "LRLine" || plot.PlotType == "LRChannel" || plot.PlotType == "LRBand" {
                var list []float64
                index1 = GetChartIndexByDate(chart, plot.Key1)
                index2 = GetChartIndexByDate(chart, plot.Key2)
                minIndex := int(math.Min(float64(index1), float64(index2)))
                maxIndex := int(math.Max(float64(index1), float64(index2)))
                for j := minIndex; j <= maxIndex; j++ {
                    list = append(list, inChart.Data[j].Close)
                }
                LinearRegressionEquation(chart, list)
                plot.Value1 = inChart.BChart
                plot.Value2 = inChart.KChart * float64(maxIndex - minIndex + 1) + inChart.BChart
            }else if plot.PlotType == "BoxLine" || plot.PlotType == "TironeLevels" || plot.PlotType == "QuadrantLines" {
                GetCandleRange(chart, plot)
                nHigh := inChart.NHighChart
                nLow := inChart.NLowChart
                index1 := GetChartIndexByDate(chart, plot.Key1)
                index2 := GetChartIndexByDate(chart, plot.Key2)
                plot.Key1 = GetChartDateByIndex(chart, int(math.Min(float64(index1), float64(index2))))
                plot.Key2 = GetChartDateByIndex(chart, int(math.Max(float64(index1), float64(index2))))
                plot.Value1 = nHigh
                plot.Value2 = nLow
            }
            if plot.Key1 > 0 {
                index1 = GetChartIndexByDate(chart, plot.Key1)
                mpx1 = GetChartX(chart, index1)
                mpy1 = GetChartY(chart, 0, plot.Value1)
                if inChart.GetSelectedPlot() == plot {
                    paint.FillEllipse(plot.PointColor, mpx1 - inChart.PlotPointSizeChart, mpy1 - inChart.PlotPointSizeChart, mpx1 + inChart.PlotPointSizeChart, mpy1 + inChart.PlotPointSizeChart)
                }
            }
            if plot.Key2 > 0 {
                index2 = GetChartIndexByDate(chart, plot.Key2)
                mpx2 = GetChartX(chart, index2)
                mpy2 = GetChartY(chart, 0, plot.Value2)
                if inChart.GetSelectedPlot() == plot {
                    paint.FillEllipse(plot.PointColor, mpx2 - inChart.PlotPointSizeChart, mpy2 - inChart.PlotPointSizeChart, mpx2 + inChart.PlotPointSizeChart, mpy2 + inChart.PlotPointSizeChart)
                }
            }
            if plot.Key3 > 0 {
                index3 = GetChartIndexByDate(chart, plot.Key3)
                mpx3 = GetChartX(chart, index3)
                mpy3 = GetChartY(chart, 0, plot.Value3)
                if inChart.GetSelectedPlot() == plot {
                    paint.FillEllipse(plot.PointColor, mpx3 - inChart.PlotPointSizeChart, mpy3 - inChart.PlotPointSizeChart, mpx3 + inChart.PlotPointSizeChart, mpy3 + inChart.PlotPointSizeChart)
                }
            }
            if plot.PlotType == "Line" {
                LineXY(chart, mpx1, mpy1, mpx2, mpy2, 0, 0)
                if mpx2 == mpx1 {
                    paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx1, 0, mpx1, divHeight)
                } else {
                    newX1 := inChart.LeftVScaleWidth
                    newY1 := newX1 * inChart.KChart + inChart.BChart
                    newX2 := chart.Size.Cx - inChart.RightVScaleWidth
                    newY2 := newX2 * inChart.KChart + inChart.BChart
                    paint.DrawLine(plot.LineColor, plot.LineWidth, 0, newX1, newY1, newX2, newY2)
                }
            }else if plot.PlotType == "AngleLine" {
                LineXY(chart, mpx1, mpy1, mpx2, mpy2, 0, 0)
                if mpx2 == mpx1 {
                    paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx1, 0, mpx1, divHeight)
                } else {
                    newX1 := inChart.LeftVScaleWidth
                    newY1 := newX1 * inChart.KChart + inChart.BChart
                    newX2 := chart.Size.Cx - inChart.RightVScaleWidth
                    newY2 := newX2 * inChart.KChart + inChart.BChart
                    paint.DrawLine(plot.LineColor, plot.LineWidth, 0, newX1, newY1, newX2, newY2)
                }
                LineXY(chart, mpx1, mpy1, mpx3, mpy3, 0, 0)
                if mpx3 == mpx1 {
                    paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx1, 0, mpx1, divHeight)
                } else {
                    newX1 := inChart.LeftVScaleWidth
                    newY1 := newX1 * inChart.KChart + inChart.BChart
                    newX2 := chart.Size.Cx - inChart.RightVScaleWidth
                    newY2 := newX2 * inChart.KChart + inChart.BChart
                    paint.DrawLine(plot.LineColor, plot.LineWidth, 0, newX1, newY1, newX2, newY2)
                }
            }else if plot.PlotType == "Parallel" {
                LineXY(chart, mpx1, mpy1, mpx2, mpy2, 0, 0)
                if mpx2 == mpx1 {
                    paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx1, 0, mpx1, divHeight)
                } else {
                    newX1 := inChart.LeftVScaleWidth
                    newY1 := newX1 * inChart.KChart + inChart.BChart
                    newX2 := chart.Size.Cx - inChart.RightVScaleWidth
                    newY2 := newX2 * inChart.KChart + inChart.BChart
                    paint.DrawLine(plot.LineColor, plot.LineWidth, 0, newX1, newY1, newX2, newY2)
                }
                newB := mpy3 - inChart.KChart * mpx3
                if mpx2 == mpx1 {
                    paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx3, 0, mpx3, divHeight)
                } else {
                    newX1 := inChart.LeftVScaleWidth
                    newY1 := newX1 * inChart.KChart + newB
                    newX2 := chart.Size.Cx - inChart.RightVScaleWidth
                    newY2 := newX2 * inChart.KChart + newB
                    paint.DrawLine(plot.LineColor, plot.LineWidth, 0, newX1, newY1, newX2, newY2)
                }
            }else if plot.PlotType == "Percent" {
                list := GetPercentParams(mpy1, mpy2)
                var texts []string
                texts = append(texts, "0%")
                texts = append(texts, "25%")
                texts = append(texts, "50%")
                texts = append(texts, "75%")
                texts = append(texts, "100%")
                for j := 0; j < len(list); j++ {
                    paint.DrawLine(plot.LineColor, plot.LineWidth, 0, inChart.LeftVScaleWidth, list[j], chart.Size.Cx - inChart.RightVScaleWidth, list[j])
                    tSize := paint.TextSize(texts[j], chart.Font)
                    paint.DrawText(texts[j], chart.TextColor, chart.Font, inChart.LeftVScaleWidth + 5, list[j] - tSize.Cy - 2)
                }
            }else if plot.PlotType == "FiboTimezone" {
                fValue := 1
                aIndex := index1
                pos := 1
                paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx1, 0, mpx1, divHeight)
                tSize := paint.TextSize("1", chart.Font)
                paint.DrawText("1", chart.TextColor, chart.Font, mpx1, divHeight - tSize.Cy)
                for{
                    if aIndex + fValue <= inChart.LastVisibleIndex{
                        fValue = FibonacciValue(pos)
                        newIndex := aIndex + fValue
                        newX := GetChartX(chart, newIndex)
                        paint.DrawLine(plot.LineColor, plot.LineWidth, 0, newX, 0, newX, divHeight)
                        tSize2 := paint.TextSize(ConvertIntToStr(fValue), chart.Font)
                        paint.DrawText(ConvertIntToStr(fValue), chart.TextColor, chart.Font, newX, divHeight - tSize2.Cy)
                        pos += 1
                    }else{
                        break
                    }
                }
            }else if plot.PlotType == "SpeedResist" {
                paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx1, mpy1, mpx2, mpy2)
                if mpx1 != mpx2 && mpy1 != mpy2 {
                    firstP := CreatePoint(mpx2, mpy2 - (mpy2 - mpy1) / 3)
                    secondP := CreatePoint(mpx2, mpy2 - (mpy2 - mpy1) * 2 / 3)
                    startP := CreatePoint(mpx1, mpy1)
                    fK := 0.0
                    fB := 0.0
                    sK := 0.0
                    sB := 0.0
                    LineXY(chart, startP.X, startP.Y, firstP.X, firstP.Y, 0, 0)
                    fK = inChart.KChart
                    fB = inChart.BChart
                    LineXY(chart, startP.X, startP.Y, secondP.X, secondP.Y, 0, 0)
                    sK = inChart.KChart
                    sB = inChart.BChart
                    newYF := 0.0
                    newYS := 0.0
                    newX := 0.0
                    if mpx2 > mpx1 {
                        newYF = fK * (chart.Size.Cx - inChart.RightVScaleWidth) + fB
                        newYS = sK * (chart.Size.Cx - inChart.RightVScaleWidth) + sB
                        newX = (chart.Size.Cx - inChart.RightVScaleWidth)
                    }else {
                        newYF = fB
                        newYS = sB
                        newX = inChart.LeftVScaleWidth
                    }
                    paint.DrawLine(plot.LineColor, plot.LineWidth, 0, startP.X, startP.Y, newX, newYF)
                    paint.DrawLine(plot.LineColor, plot.LineWidth, 0, startP.X, startP.Y, newX, newYS)
                }
            }else if plot.PlotType == "FiboFanline" {
                paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx1, mpy1, mpx2, mpy2)
                if mpx1 != mpx2 && mpy1 != mpy2 {
                    firstP := CreatePoint(mpx2, mpy2 - (mpy2 - mpy1) * 0.382)
                    secondP := CreatePoint(mpx2, mpy2 - (mpy2 - mpy1) * 0.5)
                    thirdP := CreatePoint(mpx2, mpy2 - (mpy2 - mpy1) * 0.618)
                    startP := CreatePoint(mpx1, mpy1)
                    var listP []FCPoint
                    listP = append(listP, firstP)
                    listP = append(listP, secondP)
                    listP = append(listP, thirdP)
                    listSize := len(listP)
                    for j := 0; j < listSize; j++ {
                        //获取直线参数
                        LineXY(chart, startP.X, startP.Y, listP[j].X, listP[j].Y, 0, 0)
                        newX := 0.0
                        newY := 0.0
                        if mpx2 > mpx1 {
                            newY = inChart.KChart * (chart.Size.Cx - inChart.RightVScaleWidth) + inChart.BChart
                            newX = (chart.Size.Cx - inChart.RightVScaleWidth)
                        }else {
                            newY = inChart.BChart
                            newX = inChart.LeftVScaleWidth
                        }
                        paint.DrawLine(plot.LineColor, plot.LineWidth, 0, startP.X, startP.Y, newX, newY)
                    }
                }
            }else if plot.PlotType == "LRLine"{
                paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx1, mpy1, mpx2, mpy2)
            }else if plot.PlotType == "LRBand" {
                paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx1, mpy1, mpx2, mpy2)
                GetLRBandRange(chart, plot, inChart.KChart, inChart.BChart)
                mpy1 = GetChartY(chart, 0, plot.Value1 + inChart.UpSubValue)
                mpy2 = GetChartY(chart, 0, plot.Value2 + inChart.UpSubValue)
                paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx1, mpy1, mpx2, mpy2)
                mpy1 = GetChartY(chart, 0, plot.Value1 - inChart.DownSubValue)
                mpy2 = GetChartY(chart, 0, plot.Value2 - inChart.DownSubValue)
                paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx1, mpy1, mpx2, mpy2)
            }else if plot.PlotType == "LRChannel" {
                GetLRBandRange(chart, plot, inChart.KChart, inChart.BChart)
                LineXY(chart, mpx1, mpy1, mpx2, mpy2, 0, 0)
                rightX := chart.Size.Cx - inChart.RightVScaleWidth
                rightY := rightX * inChart.KChart + inChart.BChart
                paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx1, mpy1, rightX, rightY)
                mpy1 = GetChartY(chart, 0, plot.Value1 + inChart.UpSubValue)
                mpy2 = GetChartY(chart, 0, plot.Value2 + inChart.UpSubValue)
                LineXY(chart, mpx1, mpy1, mpx2, mpy2, 0, 0)
                rightY = rightX * inChart.KChart + inChart.BChart
                paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx1, mpy1, rightX, rightY)
                mpy1 = GetChartY(chart, 0, plot.Value1 - inChart.DownSubValue)
                mpy2 = GetChartY(chart, 0, plot.Value2 - inChart.DownSubValue)
                LineXY(chart, mpx1, mpy1, mpx2, mpy2, 0, 0)
                rightY = rightX * inChart.KChart + inChart.BChart
                paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx1, mpy1, rightX, rightY)
            }else if plot.PlotType == "Segment" {
                paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx1, mpy1, mpx2, mpy2)
            } else if plot.PlotType == "Ray" {
                LineXY(chart, mpx1, mpy1, mpx2, mpy2, 0, 0)
                if inChart.KChart != 0 || inChart.BChart != 0 {
                    leftX := inChart.LeftVScaleWidth
                    leftY := leftX * inChart.KChart + inChart.BChart
                    rightX := chart.Size.Cx - inChart.RightVScaleWidth
                    rightY := rightX * inChart.KChart + inChart.BChart
                    if mpx1 >= mpx2 {
                        paint.DrawLine(plot.LineColor, plot.LineWidth, 0, leftX, leftY, mpx1, mpy1)
                    } else {
                        paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx1, mpy1, rightX, rightY)
                    }
                }else {
                    if mpy1 >= mpy2 {
                        paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx1, mpy1, mpx1, 0)
                    } else {
                        paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx1, mpy1, mpx1, divHeight)
                    }
                }
            }else if plot.PlotType == "Triangle" {
                paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx1, mpy1, mpx2, mpy2)
                paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx2, mpy2, mpx3, mpy3)
                paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx1, mpy1, mpx3, mpy3)
            }else if plot.PlotType == "SymmetricTriangle" {
                if mpx2 != mpx1 {
                    a := (mpy2 - mpy1) / (mpx2 - mpx1)
                    b := mpy1 - a * mpx1
                    c := -a
                    d := mpy3 - c * mpx3
                    leftX := inChart.LeftVScaleWidth
                    leftY := leftX * a + b
                    rightX := chart.Size.Cx - inChart.RightVScaleWidth
                    rightY := rightX * a + b
                    paint.DrawLine(plot.LineColor, plot.LineWidth, 0, leftX, leftY, rightX, rightY)
                    leftY = leftX * c + d
                    rightY = rightX * c + d
                    paint.DrawLine(plot.LineColor, plot.LineWidth, 0, leftX, leftY, rightX, rightY)
                } else {
                    paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx1, 0, mpx1, divHeight)
                    paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx3, 0, mpx3, divHeight)
                }
            }else if plot.PlotType == "Rect" {
                sX1 := math.Min(mpx1, mpx2)
                sY1 := math.Min(mpy1, mpy2)
                sX2 := math.Max(mpx1, mpx2)
                sY2 := math.Max(mpy1, mpy2)
                paint.DrawRect(plot.LineColor, plot.LineWidth, 0, sX1, sY1, sX2, sY2)
            } else if plot.PlotType == "Cycle" {
                r := math.Sqrt(math.Abs((mpx2 - mpx1) * (mpx2 - mpx1) + (mpy2 - mpy1) * (mpy2 - mpy1)))
                paint.DrawEllipse(plot.LineColor, plot.LineWidth, 0, mpx1 - r, mpy1 - r, mpx1 + r, mpy1 + r)
            } else if plot.PlotType == "CircumCycle" {
                EllipseOR(chart, mpx1, mpy1, mpx2, mpy2, mpx3, mpy3)
                paint.DrawEllipse(plot.LineColor, plot.LineWidth, 0, inChart.OXChart - inChart.RChart, inChart.OYChart - inChart.RChart, inChart.OXChart + inChart.RChart, inChart.OYChart + inChart.RChart)
            }else if plot.PlotType == "Ellipse" {
                x1 := 0.0
                y1 := 0.0
                x2 := 0.0
                y2 := 0.0
                if mpx1 <= mpx2 {
                    x1 = mpx2
                    y1 = mpy2
                    x2 = mpx1
                    y2 = mpy1
                } else {
                    x1 = mpx1
                    y1 = mpy1
                    x2 = mpx2
                    y2 = mpy2
                }
                x := x1 - (x1 - x2)
                y := 0.0
                width := (x1 - x2) * 2
                height := 0.0
                if y1 >= y2 {
                    height = (y1 - y2) * 2
                }else {
                    height = (y2 - y1) * 2
                }
                y = y2 - height / 2
                paint.DrawEllipse(plot.LineColor, plot.LineWidth, 0, x, y, x + width, y + height)
            }else if plot.PlotType == "ParalleGram" {
                Parallelogram(chart, mpx1, mpy1, mpx2, mpy2, mpx3, mpy3)
                paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx1, mpy1, mpx2, mpy2)
                paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx2, mpy2, mpx3, mpy3)
                paint.DrawLine(plot.LineColor, plot.LineWidth, 0, mpx3, mpy3, inChart.X4Chart, inChart.Y4Chart)
                paint.DrawLine(plot.LineColor, plot.LineWidth, 0, inChart.X4Chart, inChart.Y4Chart, mpx1, mpy1)
            }else if plot.PlotType == "BoxLine" {
                sX1 := math.Min(mpx1, mpx2)
                sY1 := math.Min(mpy1, mpy2)
                sX2 := math.Max(mpx1, mpx2)
                sY2 := math.Max(mpy1, mpy2)
                paint.DrawRect(plot.LineColor, plot.LineWidth, 0, sX1, sY1, sX2, sY2)
                paint.DrawText(ConvertIntToStr(int(math.Abs(float64(index2 - index1)) + 1)), chart.TextColor, chart.Font, sX1 + 2, sY1 + 2)
                var closeList []float64
                for j := index1; j <= index2; j++ {
                    closeList = append(closeList, inChart.Data[j].Close)
                }
                avgClose := AvgValue(closeList)
                closeY := GetChartY(chart, 0, avgClose)
                paint.DrawLine(plot.LineColor, plot.LineWidth, 0, sX1, closeY, sX2, closeY)
                drawAvg := ToFixed(avgClose, inChart.CandleDigit)
                tSize := paint.TextSize(drawAvg, chart.Font)
                paint.DrawText(drawAvg, chart.TextColor, chart.Font, sX1 + 2, closeY - tSize.Cy - 2)
            }else if plot.PlotType == "TironeLevels" {
                sX1 := math.Min(mpx1, mpx2)
                sY1 := math.Min(mpy1, mpy2)
                sX2 := math.Max(mpx1, mpx2)
                sY2 := math.Max(mpy1, mpy2)
                paint.DrawLine(plot.LineColor, plot.LineWidth, 0, sX1, sY1, sX2, sY1)
                paint.DrawLine(plot.LineColor, plot.LineWidth, 0, sX1, sY2, sX2, sY2)
                paint.DrawLine(plot.LineColor, plot.LineWidth, 0, sX1 + (sX2 - sX1) / 2, sY1, sX1 + (sX2 - sX1) / 2, sY2)
                t2 := inChart.NHighChart - (inChart.NHighChart - inChart.NLowChart) / 3
                t3 := inChart.NHighChart - (inChart.NHighChart - inChart.NLowChart) / 2
                t4 := inChart.NHighChart - 2 * (inChart.NHighChart - inChart.NLowChart) / 3
                var tList []float64
                tList = append(tList, t2)
                tList = append(tList, t3)
                tList = append(tList, t4)
                for j := 0; j < len(tList); j++ {
                    y := GetChartY(chart, 0, tList[j])
                    //画直线
                    paint.DrawLine(plot.LineColor, plot.LineWidth, 0, inChart.LeftVScaleWidth, y, chart.Size.Cx - inChart.RightVScaleWidth, y)
                    str := ToFixed(tList[j], inChart.CandleDigit)
                    tSize := paint.TextSize(str, chart.Font)
                    paint.DrawText(str, chart.TextColor, chart.Font, inChart.LeftVScaleWidth + 2, y - tSize.Cy - 2)
                }
            }else if plot.PlotType == "QuadrantLines" {
                sX1 := math.Min(mpx1, mpx2)
                sY1 := math.Min(mpy1, mpy2)
                sX2 := math.Max(mpx1, mpx2)
                sY2 := math.Max(mpy1, mpy2)
                paint.DrawLine(plot.LineColor, plot.LineWidth, 0, sX1, sY1, sX2, sY1)
                paint.DrawLine(plot.LineColor, plot.LineWidth, 0, sX1, sY2, sX2, sY2)
                t2 := inChart.NHighChart - (inChart.NHighChart - inChart.NLowChart) / 4
                t3 := inChart.NHighChart - (inChart.NHighChart - inChart.NLowChart) / 2
                t4 := inChart.NHighChart - 3 * (inChart.NHighChart - inChart.NLowChart) / 4
                var tList []float64
                tList = append(tList, t2)
                tList = append(tList, t3)
                tList = append(tList, t4)
                for j := 0; j < len(tList); j++ {
                    y := GetChartY(chart, 0, tList[j])
                    //画直线
                    paint.DrawLine(plot.LineColor, plot.LineWidth, 0, sX1, y, sX2, y)
                }
            }else if plot.PlotType == "GoldenRatio" {
                sY1 := math.Min(mpy1, mpy2)
                sY2 := math.Max(mpy1, mpy2)
                var ranges []float64
                ranges = append(ranges, 0)
                ranges = append(ranges, 0.236)
                ranges = append(ranges, 0.382)
                ranges = append(ranges, 0.5)
                ranges = append(ranges, 0.618)
                ranges = append(ranges, 0.809)
                ranges = append(ranges, 1)
                ranges = append(ranges, 1.382)
                ranges = append(ranges, 1.618)
                ranges = append(ranges, 2)
                ranges = append(ranges, 2.382)
                ranges = append(ranges, 2.618)
                for j := 0; j < len(ranges); j++ {
                    newY := 0.0
                    if sY1 <= sY2{
                        newY = sY1 + (sY2 - sY1) * ranges[j]
                    }else{
                        newY = sY2 + (sY1 - sY2) * (1 - ranges[j])
                    }
                    paint.DrawLine(plot.LineColor, plot.LineWidth, 0, inChart.LeftVScaleWidth, newY, chart.Size.Cx - inChart.RightVScaleWidth, newY)
                    newPoint := CreatePoint(0, newY)
                    value := GetCandleDivValue(chart, newPoint)
                    str := ToFixed(value, inChart.CandleDigit)
                    tSize := paint.TextSize(str, chart.Font)
                    paint.DrawText(str, chart.TextColor, chart.Font, inChart.LeftVScaleWidth + 2, newY - tSize.Cy - 2)
                }
            }else if plot.PlotType == "ArrowSegment" {
                arrowSize := 24.0
                slopy := 0.0
                cosy := 0.0
                siny := 0.0
                slopy = math.Atan2(mpy1 - mpy2, mpx1 - mpx2)
                cosy = math.Cos(slopy)
                siny = math.Sin(slopy)
                ptPoint := CreatePoint(0, 0)
                ptPoint.X = mpx2
                ptPoint.Y = mpy2
                var pts []FCPoint
                pts = append(pts, CreatePoint(ptPoint.X, ptPoint.Y))
                pts = append(pts, CreatePoint(ptPoint.X + (arrowSize * cosy - (arrowSize / 2.0 * siny) + 0.5), ptPoint.Y + (arrowSize * siny + (arrowSize / 2.0 * cosy) + 0.5)))
                pts = append(pts, CreatePoint(ptPoint.X + (arrowSize * cosy + arrowSize / 2.0 * siny + 0.5), ptPoint.Y - (arrowSize / 2.0 * cosy - arrowSize * siny + 0.5)))
                arrowSize = 20.0
                ptPoint2 := CreatePoint(0, 0)
                ptPoint2.X = mpx2
                ptPoint2.Y = mpy2
                var pts2 []FCPoint
                pts2 = append(pts2, CreatePoint(ptPoint2.X, ptPoint2.Y))
                pts2 = append(pts2, CreatePoint(ptPoint2.X + (arrowSize * cosy - (arrowSize / 2.0 * siny) + 0.5), ptPoint2.Y + (arrowSize * siny + (arrowSize / 2.0 * cosy) + 0.5)))
                pts2 = append(pts2, CreatePoint(ptPoint2.X + (arrowSize * cosy + arrowSize / 2.0 * siny + 0.5), ptPoint2.Y - (arrowSize / 2.0 * cosy - arrowSize * siny + 0.5)))
                LineXY(chart, pts2[1].X, pts2[1].Y, pts2[2].X, pts2[2].Y, 0, 0)
                newX1 := 0.0
                newY1 := 0.0
                newX2 := 0.0
                newY2 := 0.0
                if pts2[1].X > pts2[2].X {
                    newX1 = pts2[2].X + (pts2[1].X - pts2[2].X) / 3
                    newX2 = pts2[2].X + (pts2[1].X - pts2[2].X) * 2 / 3
                } else {
                    newX1 = pts2[1].X + (pts2[2].X - pts2[1].X) / 3
                    newX2 = pts2[1].X + (pts2[2].X - pts2[1].X) * 2 / 3
                }
                if inChart.KChart == 0 && inChart.BChart == 0 {
                    if pts2[1].Y > pts2[2].Y {
                        newY1 = pts2[2].Y + (pts2[1].Y - pts2[2].Y) / 3
                        newY2 = pts2[2].Y + (pts2[1].Y - pts2[2].Y) * 2 / 3
                    } else {
                        newY1 = pts2[1].Y + (pts2[2].Y - pts2[1].Y) / 3
                        newY2 = pts2[1].Y + (pts2[2].Y - pts2[1].Y) * 2 / 3
                    }
                } else {
                    newY1 = (inChart.KChart * newX1) + inChart.BChart
                    newY2 = (inChart.KChart * newX2) + inChart.BChart
                }
                p2 := CreatePoint(newX1, newY1)
                pts2[1] = p2
                p3 := CreatePoint(newX2, newY2)
                pts2[2] = p3
                var drawPoints []FCPoint
                drawPoints = append(drawPoints, CreatePoint(ptPoint.X, ptPoint.Y))
                drawPoints = append(drawPoints, CreatePoint(pts[1].X, pts[1].Y))
                if mpy1 >= mpy2 {
                    drawPoints = append(drawPoints, CreatePoint(pts2[1].X, pts2[1].Y))
                } else {
                    drawPoints = append(drawPoints, CreatePoint(pts2[2].X, pts2[2].Y))
                }
                drawPoints = append(drawPoints, CreatePoint(mpx1, mpy1))
                if mpy1 >= mpy2 {
                    drawPoints = append(drawPoints, CreatePoint(pts2[2].X, pts2[2].Y))
                } else {
                    drawPoints = append(drawPoints, CreatePoint(pts2[1].X, pts2[1].Y))
                }
                drawPoints = append(drawPoints, CreatePoint(pts[2].X, pts[2].Y))
                paint.FillPolygon(plot.LineColor, drawPoints)
            }
        }
        paint.Restore()
    }
}

/*
* 绘制图表
* chart:图表
* paint:绘图对象
* clipRect:裁剪区域
*/
func DrawChartStock(chart *FCView, paint *FCPaint, clipRect FCRect) {
    inChart := chart.GetChart()
    candleHeight := GetCandleDivHeight(chart)
    volHeight := GetVolDivHeight(chart)
    indHeight := GetIndDivHeight(chart)
    isTrend := false
    if inChart.Cycle == "trend"{
        isTrend = true
    }
    cWidth := float64(int((inChart.HScalePixel - 3) / 2))
    if cWidth < 0 {
        cWidth = 0
    }
    lastValidIndex := inChart.LastVisibleIndex
    if inChart.LastValidIndex != -1 {
        lastValidIndex = inChart.LastValidIndex
    }
    if len(inChart.Data) > 0 {
        maxVisibleRecord := GetChartMaxVisibleCount(chart, inChart.HScalePixel, GetChartWorkAreaWidth(chart))
        if isTrend {
            var drawPoints []FCPoint
            for i := inChart.FirstVisibleIndex; i <= lastValidIndex; i++ {
                x := GetChartX(chart, i)
                close := inChart.Data[i].Close
                closeY := GetChartY(chart, 0, close)
                drawPoints = append(drawPoints, CreatePoint(x, closeY))
            }
            paint.DrawPolyline(inChart.IndicatorColors[7], inChart.LineWidthChart, 0, drawPoints)
        }
        hasMinTag := false
        hasMaxTag := false
        for i := inChart.FirstVisibleIndex; i <= lastValidIndex; i++ {
            x := GetChartX(chart, i)
            open := inChart.Data[i].Open
            close := inChart.Data[i].Close
            high := inChart.Data[i].High
            low := inChart.Data[i].Low
            openY := GetChartY(chart, 0, open)
            closeY := GetChartY(chart, 0, close)
            highY := GetChartY(chart, 0, high)
            lowY := GetChartY(chart, 0, low)
            if close >= open {
                if !isTrend {
                    paint.DrawLine(inChart.UpColor, inChart.LineWidthChart, 0, x, highY, x, lowY)
                    if cWidth > 0 {
                        if close == open {
                            paint.DrawLine(inChart.UpColor, inChart.LineWidthChart, 0, x - cWidth, closeY, x + cWidth, closeY)
                        }else {
                            if inChart.CandleStyle == "rect2"{
                                paint.FillRect(chart.BackColor, x - cWidth, closeY, x + cWidth, openY)
                                paint.DrawRect(inChart.UpColor, 1, 0, x - cWidth, closeY, x + cWidth, openY)
                            }else{
                                paint.FillRect(inChart.UpColor, x - cWidth, closeY, x + cWidth, openY)
                            }
                        }
                    }
                } 
            } else {
                if !isTrend {
                    paint.DrawLine(inChart.DownColor, inChart.LineWidthChart, 0, x, highY, x, lowY)
                    if cWidth > 0 {
                        paint.FillRect(inChart.DownColor, x - cWidth, openY, x + cWidth, closeY)
                    }
                }
            }
            if inChart.SelectShape == "CANDLE" {
                kPInterval := int(maxVisibleRecord / 30)
                if kPInterval < 2 {
                    kPInterval = 3
                }
                if i % kPInterval == 0 {
                    if !isTrend {
                        paint.FillRect(inChart.IndicatorColors[0], x - 3, closeY - 3, x + 3, closeY + 3)
                    } 
                }
            }
            if !isTrend {
                if !hasMaxTag {
                    if high == inChart.CandleMax {
                        tag := ToFixed(high, inChart.CandleDigit)
                        tSize := paint.TextSize(tag, chart.Font)
                        paint.DrawText(tag, chart.TextColor, chart.Font, x - tSize.Cx / 2, highY - tSize.Cy / 2 - 2)
                        hasMaxTag = true
                    }
                }
                if !hasMinTag {
                    if low == inChart.CandleMin {
                        tag := ToFixed(low, inChart.CandleDigit)
                        tSize := paint.TextSize(tag, chart.Font)
                        paint.DrawText(tag, chart.TextColor, chart.Font, x - tSize.Cx / 2, lowY + 2 + tSize.Cy / 2)
                        hasMinTag = true
                    }
                }
            }
        }
        for i := inChart.FirstVisibleIndex; i <= lastValidIndex; i++ {
            x := GetChartX(chart, i)
            open := inChart.Data[i].Open
            close := inChart.Data[i].Close
            volY := 0.0
            zeroY := 0.0
            if volHeight > 0 {
                volume := inChart.Data[i].Volume
                volY = GetChartY(chart, 1, volume)
                zeroY = GetChartY(chart, 1, 0)
            }
            if close >= open {
                if isTrend {
                    if volHeight > 0 {
                        paint.DrawLine(inChart.IndicatorColors[6], inChart.LineWidthChart, 0, x, volY, x, zeroY)
                    }
                } else {
                    if cWidth > 0 {
                        if volHeight > 0 {
                            if inChart.BarStyle == "rect2"{
                                paint.FillRect(chart.BackColor, x - cWidth, volY, x + cWidth, zeroY)
                                paint.DrawRect(inChart.UpColor, 1, 0, x - cWidth, volY, x + cWidth, zeroY)
                            }else{
                                paint.FillRect(inChart.UpColor, x - cWidth, volY, x + cWidth, zeroY)
                            }
                        }
                    } else {
                        if volHeight > 0 {
                            paint.DrawLine(inChart.UpColor, inChart.LineWidthChart, 0, x - cWidth, volY, x + cWidth, zeroY)
                        }
                    }
                }
            } else {
                if isTrend {
                    if volHeight > 0 {
                        paint.DrawLine(inChart.IndicatorColors[6], inChart.LineWidthChart, 0, x, volY, x, zeroY)
                    }
                } else {
                    if cWidth > 0 {
                        if volHeight > 0 {
                            paint.FillRect(inChart.DownColor, x - cWidth, volY, x + cWidth, zeroY)
                        }
                    } else {
                        if volHeight > 0 {
                            paint.DrawLine(inChart.DownColor, inChart.LineWidthChart, 0, x - cWidth, volY, x + cWidth, zeroY)
                        }
                    }
                }
            }
            if inChart.SelectShape == "VOL" {
                kPInterval := int(maxVisibleRecord / 30)
                if kPInterval < 2 {
                    kPInterval = 3
                }
                if i % kPInterval == 0 {
                    paint.FillRect(inChart.IndicatorColors[0], x - 3, volY - 3, x + 3, volY + 3)
                }
            }
        }
        if !isTrend{
            paint.Save()
            paint.SetClip(inChart.LeftVScaleWidth, 0, chart.Size.Cx - inChart.RightVScaleWidth, candleHeight)
            if inChart.MainIndicator == "BOLL" {
                if inChart.SelectShape == inChart.MainIndicator && inChart.SelectShapeEx == "MID"{
					DrawChartLines(chart, paint, clipRect, 0, inChart.BollMid, inChart.IndicatorColors[0], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 0, inChart.BollMid, inChart.IndicatorColors[0], false)
                }
				if inChart.SelectShape == inChart.MainIndicator && inChart.SelectShapeEx == "UP"{
					DrawChartLines(chart, paint, clipRect, 0, inChart.BollUp, inChart.IndicatorColors[1], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 0, inChart.BollUp, inChart.IndicatorColors[1], false)
                }
				if inChart.SelectShape == inChart.MainIndicator && inChart.SelectShapeEx == "DOWN"{
					DrawChartLines(chart, paint, clipRect, 0, inChart.BollDown, inChart.IndicatorColors[2], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 0, inChart.BollDown, inChart.IndicatorColors[2], false)
                }
            } else if inChart.MainIndicator == "MA" {
                if inChart.SelectShape == inChart.MainIndicator && inChart.SelectShapeEx == "5"{
					DrawChartLines(chart, paint, clipRect, 0, inChart.Ma5, inChart.IndicatorColors[0], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 0, inChart.Ma5, inChart.IndicatorColors[0], false)
                }
				if inChart.SelectShape == inChart.MainIndicator && inChart.SelectShapeEx == "10"{
					DrawChartLines(chart, paint, clipRect, 0, inChart.Ma10, inChart.IndicatorColors[1], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 0, inChart.Ma10, inChart.IndicatorColors[1], false)
                }
				if inChart.SelectShape == inChart.MainIndicator && inChart.SelectShapeEx == "20"{
					DrawChartLines(chart, paint, clipRect, 0, inChart.Ma20, inChart.IndicatorColors[2], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 0, inChart.Ma20, inChart.IndicatorColors[2], false)
                }
				if inChart.SelectShape == inChart.MainIndicator && inChart.SelectShapeEx == "30"{
					DrawChartLines(chart, paint, clipRect, 0, inChart.Ma30, inChart.IndicatorColors[3], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 0, inChart.Ma30, inChart.IndicatorColors[3], false)
                }
				if inChart.SelectShape == inChart.MainIndicator && inChart.SelectShapeEx == "120"{
					DrawChartLines(chart, paint, clipRect, 0, inChart.Ma120, inChart.IndicatorColors[4], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 0, inChart.Ma120, inChart.IndicatorColors[4], false)
                }
				if inChart.SelectShape == inChart.MainIndicator && inChart.SelectShapeEx == "250"{
					DrawChartLines(chart, paint, clipRect, 0, inChart.Ma250, inChart.IndicatorColors[5], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 0, inChart.Ma250, inChart.IndicatorColors[5], false)
                }
            }
            paint.Restore()
        }
        if indHeight > 0 {
            if inChart.ShowIndicator == "MACD" {
                zeroY := GetChartY(chart, 2, 0)
                paint.DrawLine(inChart.IndicatorColors[4], inChart.LineWidthChart, 0, inChart.LeftVScaleWidth, zeroY, GetChartX(chart, inChart.LastVisibleIndex), zeroY)
                for i := inChart.FirstVisibleIndex; i <= lastValidIndex; i++ {
                    x := GetChartX(chart, i)
                    macd := inChart.Allmacdarr[i]
                    macdY := GetChartY(chart, 2, macd)
                    if macdY < zeroY {
                        paint.DrawLine(inChart.IndicatorColors[3], inChart.LineWidthChart, 0, x, macdY, x, zeroY)
                    } else {
                        paint.DrawLine(inChart.IndicatorColors[4], inChart.LineWidthChart, 0, x, macdY, x, zeroY)
                    }
                    if inChart.SelectShape == inChart.ShowIndicator && inChart.SelectShapeEx == "MACD" {
                        kPInterval := int(maxVisibleRecord / 30)
                        if kPInterval < 2 {
                            kPInterval = 3
                        }
                        if i % kPInterval == 0 {
                            paint.FillRect(inChart.IndicatorColors[4], x - 3, macdY - 3, x + 3, macdY + 3)
                        }
                    }
                }
                if inChart.SelectShape == inChart.ShowIndicator && inChart.SelectShapeEx == "DIF"{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Alldifarr, inChart.IndicatorColors[0], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Alldifarr, inChart.IndicatorColors[0], false)
                }
				if inChart.SelectShape == inChart.ShowIndicator && inChart.SelectShapeEx == "DEA"{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Alldeaarr, inChart.IndicatorColors[1], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Alldeaarr, inChart.IndicatorColors[1], false)
                }
            } else if inChart.ShowIndicator == "KDJ"{
                if inChart.SelectShape == inChart.ShowIndicator && inChart.SelectShapeEx == "K"{
					DrawChartLines(chart, paint, clipRect, 2, inChart.KdjK, inChart.IndicatorColors[0], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 2, inChart.KdjK, inChart.IndicatorColors[0], false)
                }
				if inChart.SelectShape == inChart.ShowIndicator && inChart.SelectShapeEx == "D"{
					DrawChartLines(chart, paint, clipRect, 2, inChart.KdjD, inChart.IndicatorColors[1], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 2, inChart.KdjD, inChart.IndicatorColors[1], false)
                }
				if inChart.SelectShape == inChart.ShowIndicator && inChart.SelectShapeEx == "J"{
					DrawChartLines(chart, paint, clipRect, 2, inChart.KdjJ, inChart.IndicatorColors[2], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 2, inChart.KdjJ, inChart.IndicatorColors[2], false)
                }
            } else if inChart.ShowIndicator == "RSI" {
                if inChart.SelectShape == inChart.ShowIndicator && inChart.SelectShapeEx == "6"{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Rsi1, inChart.IndicatorColors[5], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Rsi1, inChart.IndicatorColors[5], false)
                }
				if inChart.SelectShape == inChart.ShowIndicator && inChart.SelectShapeEx == "12"{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Rsi2, inChart.IndicatorColors[1], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Rsi2, inChart.IndicatorColors[1], false)
                }
				if inChart.SelectShape == inChart.ShowIndicator && inChart.SelectShapeEx == "24"{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Rsi3, inChart.IndicatorColors[2], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Rsi3, inChart.IndicatorColors[2], false)
                }
            }else if inChart.ShowIndicator == "BIAS" {
                if inChart.SelectShape == inChart.ShowIndicator && inChart.SelectShapeEx == "1"{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Bias1, inChart.IndicatorColors[5], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Bias1, inChart.IndicatorColors[5], false)
                }
				if inChart.SelectShape == inChart.ShowIndicator && inChart.SelectShapeEx == "2"{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Bias2, inChart.IndicatorColors[1], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Bias2, inChart.IndicatorColors[1], false)
                }
				if inChart.SelectShape == inChart.ShowIndicator && inChart.SelectShapeEx == "3"{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Bias3, inChart.IndicatorColors[2], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Bias3, inChart.IndicatorColors[2], false)
                }
            }else if inChart.ShowIndicator == "ROC" {
                if inChart.SelectShape == inChart.ShowIndicator && inChart.SelectShapeEx == "ROC"{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Roc, inChart.IndicatorColors[0], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Roc, inChart.IndicatorColors[0], false)
                }
				if inChart.SelectShape == inChart.ShowIndicator && inChart.SelectShapeEx == "ROCMA"{
					DrawChartLines(chart, paint, clipRect, 2, inChart.RocMa, inChart.IndicatorColors[1], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 2, inChart.RocMa, inChart.IndicatorColors[1], false)
                }
            } else if inChart.ShowIndicator == "WR" {
                if inChart.SelectShape == inChart.ShowIndicator && inChart.SelectShapeEx == "1"{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Wr1, inChart.IndicatorColors[0], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Wr1, inChart.IndicatorColors[0], false)
                }
				if inChart.SelectShape == inChart.ShowIndicator && inChart.SelectShapeEx == "2"{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Wr2, inChart.IndicatorColors[1], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Wr2, inChart.IndicatorColors[1], false)
                }   
            } else if inChart.ShowIndicator == "CCI" {
                if inChart.SelectShape == inChart.ShowIndicator{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Cci, inChart.IndicatorColors[0], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Cci, inChart.IndicatorColors[0], false)
                }
            } else if inChart.ShowIndicator == "BBI" {
                if inChart.SelectShape == inChart.ShowIndicator{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Bbi, inChart.IndicatorColors[0], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Bbi, inChart.IndicatorColors[0], false)
                }   
            } else if inChart.ShowIndicator == "TRIX" {
                if inChart.SelectShape == inChart.ShowIndicator && inChart.SelectShapeEx == "TRIX"{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Trix, inChart.IndicatorColors[0], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Trix, inChart.IndicatorColors[0], false)
                }
				if inChart.SelectShape == inChart.ShowIndicator && inChart.SelectShapeEx == "TRIXMA"{
					DrawChartLines(chart, paint, clipRect, 2, inChart.TrixMa, inChart.IndicatorColors[1], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 2, inChart.TrixMa, inChart.IndicatorColors[1], false)
                }
            } else if inChart.ShowIndicator == "DMA" {
                if inChart.SelectShape == inChart.ShowIndicator && inChart.SelectShapeEx == "DIF"{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Dma1, inChart.IndicatorColors[0], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Dma1, inChart.IndicatorColors[0], false)
                }
				if inChart.SelectShape == inChart.ShowIndicator && inChart.SelectShapeEx == "DIFMA"{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Dma2, inChart.IndicatorColors[1], true)
                }else{
					DrawChartLines(chart, paint, clipRect, 2, inChart.Dma2, inChart.IndicatorColors[1], false)
                }
            }
        }
    }
    //绘制扩展线条
    if len(inChart.Shapes) > 0 {
        for i := 0; i < len(inChart.Shapes); i++ {
            shape := inChart.Shapes[i]
            if shape.ShapeType == "bar" {
                for j := inChart.FirstVisibleIndex; j <= lastValidIndex; j++ {
                    if len(shape.ShowHideDatas) > j && ConvertIntToStr(int(shape.ShowHideDatas[j])) == "0" {
                        continue
                    }
                    x := GetChartX(chart, j)
                    y1 := 0.0
                    if shape.LeftOrRight {
                        y1 = GetChartY(chart, shape.DivIndex, shape.Datas[j])
                    } else {
                        y1 = GetChartYInRight(chart, shape.DivIndex, shape.Datas[j])
                    }
                    if shape.Style != "2color" {
                        y2 := 0.0
                        if shape.LeftOrRight {
                            y2 = GetChartY(chart, shape.DivIndex, shape.Datas2[j])
                        } else {
                            y2 = GetChartYInRight(chart, shape.DivIndex, shape.Datas2[j])
                        }
                        if y1 >= y2 {
                            paint.FillRect(shape.Color, x - cWidth, y2, x + cWidth, y1)
                        }else {
                            paint.FillRect(shape.Color, x - cWidth, y1, x + cWidth, y2)
                        }
                    } else {
                        y2 := 0.0
                        if shape.LeftOrRight {
                            y2 = GetChartY(chart, shape.DivIndex, 0)
                        } else {
                            y2 = GetChartYInRight(chart, shape.DivIndex, 0)
                        }
                        if y1 >= y2 {
                            paint.DrawLine(shape.Color2, 1, 0, x, y1, x, y2)
                        }else {
                            paint.DrawLine(shape.Color, 1, 0, x, y1, x, y2)
                        }
                        if j == lastValidIndex {
                            paint.DrawLine(shape.Color2, 1, 0, inChart.LeftVScaleWidth, y2, chart.Size.Cx - inChart.RightVScaleWidth, y2)
                        }
                    }
                }
            }else if shape.ShapeType == "text"{
                for j := inChart.FirstVisibleIndex; j <= lastValidIndex; j++ {
                    x := GetChartX(chart, j)
                    if shape.Datas[j] != 0 {
                        y1 := 0.0
                        if shape.LeftOrRight {
                            y1 = GetChartY(chart, shape.DivIndex, shape.Value)
                        } else {
                            y1 = GetChartYInRight(chart, shape.DivIndex, shape.Value)
                        }
                        DrawText := shape.Text
                        tSize := paint.TextSize(DrawText, "Default,14")
                        paint.DrawText(DrawText, shape.Color, "Default,14", x - tSize.Cx / 2, y1 - tSize.Cy / 2)
                    }
                }
            }else {
                if shape.LeftOrRight {
                    if inChart.SelectShape == shape.ShapeName{
                        DrawChartLines(chart, paint, clipRect, shape.DivIndex, shape.Datas, shape.Color, true)
                    }else{
                        DrawChartLines(chart, paint, clipRect, shape.DivIndex, shape.Datas, shape.Color, false)
                    }
                } else {
                    if inChart.SelectShape == shape.ShapeName{
                        DrawChartLinesInRight(chart, paint, clipRect, shape.DivIndex, shape.Datas, shape.Color, true)
                    }else{
                        DrawChartLinesInRight(chart, paint, clipRect, shape.DivIndex, shape.Datas, shape.Color, false)
                    }
                }
            }
        }
    }
}

/*
* 获取数据
* chart:图表
*/
func CalcChartIndicator(chart *FCView) {
    inChart := chart.GetChart()
    ClearDataArr(chart)
    if len(inChart.Data) > 0{
        var closeArr []float64
        var highArr []float64
        var lowArr []float64
        if len(inChart.Data) > 0 {
            for i := 0; i < len(inChart.Data); i++ {
                closeArr = append(closeArr, inChart.Data[i].Close)
                highArr = append(highArr, inChart.Data[i].High)
                lowArr = append(lowArr, inChart.Data[i].Low)
            }
        }
        inChart.CloseArr = closeArr
        if inChart.MainIndicator == "BOLL" {
            GetBollData(chart, 20, closeArr)
        } else if inChart.MainIndicator == "MA" {
            inChart.Ma5 = MaValue(closeArr, 5)
            inChart.Ma10 = MaValue(closeArr, 10)
            inChart.Ma20 = MaValue(closeArr, 20)
            inChart.Ma30 = MaValue(closeArr, 30)
            inChart.Ma120 = MaValue(closeArr, 120)
            inChart.Ma250 = MaValue(closeArr, 250)
        }
        if inChart.ShowIndicator == "BIAS" {
            GetBIASData(chart, 6, 12, 24, closeArr)
        }else if inChart.ShowIndicator == "DMA"{
            GetDMAData(chart, 10, 50, closeArr)
        }else if inChart.ShowIndicator == "BBI"{
            GetBBIData(chart, closeArr, 3, 6, 12, 24)
        }else if inChart.ShowIndicator == "RSI"{
            GetRSIData(chart, 6, 12, 24, closeArr)
        }else if inChart.ShowIndicator == "ROC"{
            GetRocData(chart, 12, 6, closeArr)
        }else if inChart.ShowIndicator == "TRIX"{
            GetTRIXData(chart, 12, 9, closeArr)
        }else if inChart.ShowIndicator == "KDJ"{
            GetKDJData(chart, highArr, lowArr, closeArr, 9, 3, 3)
        }else if inChart.ShowIndicator == "WR"{
            GetWRData(chart, highArr, lowArr, closeArr, 5, 10)
        }else if inChart.ShowIndicator == "CCI"{
            GetCCIData(chart, highArr, lowArr, 14, closeArr)
        }else if inChart.ShowIndicator == "MACD" {
            //缓存MACD数据
            inChart.Allema12 = append(inChart.Allema12, closeArr[0])
            inChart.Allema26 = append(inChart.Allema26, closeArr[0])
            inChart.Alldeaarr = append(inChart.Alldeaarr, 0)
            for i := 1; i < len(closeArr); i++ {
                lastEMA := GetEMA(12, closeArr[i], inChart.Allema12[i - 1])
                lastEMA2 := GetEMA(26, closeArr[i], inChart.Allema26[i - 1])
                inChart.Allema12 = append(inChart.Allema12, lastEMA)
                inChart.Allema26 = append(inChart.Allema26, lastEMA2)
            }
            inChart.Alldifarr = getDIF(inChart.Allema12, inChart.Allema26)
            for i := 1; i < len(inChart.Alldifarr); i++ {
                inChart.Alldeaarr = append(inChart.Alldeaarr, inChart.Alldeaarr[i - 1] * 8 / 10 + inChart.Alldifarr[i] * 2 / 10)
            }
            inChart.Allmacdarr = GetMACD(inChart.Alldifarr, inChart.Alldeaarr)
        }
    }
    if inChart.OnCalculateChartMaxMin != nil{
        inChart.OnCalculateChartMaxMin(chart)
    }else if chart.GetPaint().OnCalculateChartMaxMin != nil{
        chart.GetPaint().OnCalculateChartMaxMin(chart)
    }else{
        CalculateChartMaxMin(chart)
    }
}

/*
* 计算EMA
* n:周期
* value:当前数据
* lastEMA:上期数据
*/
func GetEMA(n int, value float64, lastEMA float64)(float64) {
    return(value * 2 + lastEMA * float64(n - 1)) / float64(n + 1)
}

/*
* 计算MACD
* dif:DIF数据
* dea:DEA数据
*/
func GetMACD(dif []float64, dea []float64)([]float64) {
    var result []float64
	length := len(dif)
	for i := 0; i < length; i++ {
			result = append(result, (dif[i] - dea[i]) * 2.0)
	}
	return result
}

/*
* 计算DIF
* close12:12日数据
* close26:26日数据
*/
func getDIF(close12 []float64, close26 []float64) ([]float64) {
    var result []float64
    for i := 0; i < len(close12); i++ {
        result = append(result, close12[i] - close26[i])
    }
    return result
}

/*
* 清除缓存数据方法
* chart:图表
*/
func ClearDataArr(chart *FCView) {
    inChart := chart.GetChart()
    var allema12[] float64
    inChart.Allema12 = allema12
    var allema26[] float64
    inChart.Allema26 = allema26
    var alldifarr[] float64
    inChart.Alldifarr = alldifarr
    var alldeaarr[] float64
    inChart.Alldeaarr = alldeaarr
    var allmacdarr[] float64
    inChart.Allmacdarr = allmacdarr
    var bollUp[] float64
    inChart.BollUp = bollUp
    var bollDown[] float64
    inChart.BollDown = bollDown
    var bollMid[] float64
    inChart.BollMid = bollMid
    var bias1[] float64
    inChart.Bias1 = bias1
    var bias2[] float64
    inChart.Bias2 = bias2
    var bias3[] float64
    inChart.Bias3 = bias3
    var kdjK[] float64
    inChart.KdjK = kdjK
    var kdjD[] float64
    inChart.KdjD = kdjD
    var kdjJ[] float64
    inChart.KdjJ = kdjJ
    var rsi1[] float64
    inChart.Rsi1 = rsi1
    var rsi2[] float64
    inChart.Rsi2 = rsi2
    var rsi3[] float64
    inChart.Rsi3 = rsi3
    var roc[] float64
    inChart.Roc = roc
    var rocMa[] float64
    inChart.RocMa = rocMa
    var wr1[] float64
    inChart.Wr1 = wr1
    var wr2[] float64
    inChart.Wr2 = wr2
    var cci[] float64
    inChart.Cci = cci
    var bbi[] float64
    inChart.Bbi = bbi
    var trix[] float64
    inChart.Trix = trix
    var trixMa[] float64
    inChart.TrixMa = trixMa
    var dma1[] float64
    inChart.Dma1 = dma1
    var dma2[] float64
    inChart.Dma2 = dma2
    var ma5[] float64
    inChart.Ma5 = ma5
    var ma10[] float64
    inChart.Ma10 = ma10
    var ma20[] float64
    inChart.Ma20 = ma20
    var ma30[] float64
    inChart.Ma30 = ma30
    var ma120[] float64
    inChart.Ma120 = ma120
    var ma250[] float64
    inChart.Ma250 = ma250
}

/*
* 判断是否选中线条
* chart:图表
* mp:坐标
* divIndex:层索引
* datas:数据
* curIndex:当前索引
*/
func SelectLines(chart *FCView, mp FCPoint, divIndex int, datas []float64, curIndex int)(bool){
    inChart := chart.GetChart()
    if len(datas) > 0 {
        topY := GetChartY(chart, divIndex, datas[curIndex])
        if inChart.HScalePixel <= 1 {
            if mp.Y >= topY - 8 && mp.Y <= topY + 8 {
                return true
            }
        } else {
            index := curIndex
            scaleX := GetChartX(chart, index)
            judgeTop := 0.0
            judgeScaleX := scaleX
            if mp.X >= scaleX {
                leftIndex := curIndex + 1
                if curIndex < inChart.LastVisibleIndex {
                    rightValue := datas[leftIndex]
                    judgeTop = GetChartY(chart, divIndex, rightValue)
                }else {
                    judgeTop = topY
                }
            }else {
                judgeScaleX = scaleX - inChart.HScalePixel
                rightIndex := curIndex - 1
                if curIndex > 0 {
                    leftValue := datas[rightIndex]
                    judgeTop = GetChartY(chart, divIndex, leftValue)
                } else {
                    judgeTop = topY
                }
            }
            lineWidth := 4.0
            judgeX := 0.0
            judgeY := 0.0
            judgeW := 0.0
            judgeH := 0.0
            if judgeTop >= topY {
                judgeX = judgeScaleX
                judgeY = topY - 2 - lineWidth
                judgeW = inChart.HScalePixel
                if judgeTop - topY + lineWidth < 4{
                    judgeH = 4
                }else{
                    judgeH = judgeTop - topY + 4 + lineWidth
                }
            }else {
                judgeX = judgeScaleX
                judgeY = judgeTop - 2 - lineWidth / 2
                judgeW = inChart.HScalePixel
                if topY - judgeTop + lineWidth < 4{
                    judgeH = 4
                }else{
                    judgeH = topY - judgeTop + 4 + lineWidth
                }
            }
            if (mp.X >= judgeX && mp.X <= judgeX + judgeW && mp.Y >= judgeY && mp.Y <= judgeY + judgeH) {

                return true
            }
        }
    }
    return false
}

/*
* 判断是否在右轴选中线条
* chart:图表
* mp:坐标
* divIndex:层索引
* datas:数据
* curIndex:当前索引
*/
func SelectLinesInRight(chart *FCView, mp FCPoint, divIndex int, datas []float64, curIndex int)(bool){
    inChart := chart.GetChart()
    if len(datas) > 0 {
        topY := GetChartYInRight(chart, divIndex, datas[curIndex])
        if inChart.HScalePixel <= 1 {
            if mp.Y >= topY - 8 && mp.Y <= topY + 8 {
                return true
            }
        } else {
            index := curIndex
            scaleX := GetChartX(chart, index)
            judgeTop := 0.0
            judgeScaleX := scaleX
            if mp.X >= scaleX {
                leftIndex := curIndex + 1
                if curIndex < inChart.LastVisibleIndex {
                    rightValue := datas[leftIndex]
                    judgeTop = GetChartYInRight(chart, divIndex, rightValue)
                }else {
                    judgeTop = topY
                }
            }else {
                judgeScaleX = scaleX - inChart.HScalePixel
                rightIndex := curIndex - 1
                if curIndex > 0 {
                    leftValue := datas[rightIndex]
                    judgeTop = GetChartYInRight(chart, divIndex, leftValue)
                } else {
                    judgeTop = topY
                }
            }
            lineWidth := 4.0
            judgeX := 0.0
            judgeY := 0.0
            judgeW := 0.0
            judgeH := 0.0
            if judgeTop >= topY {
                judgeX = judgeScaleX
                judgeY = topY - 2 - lineWidth
                judgeW = inChart.HScalePixel
                if judgeTop - topY + lineWidth < 4{
                    judgeH = 4
                }else{
                    judgeH = judgeTop - topY + 4 + lineWidth
                }
            }else {
                judgeX = judgeScaleX
                judgeY = judgeTop - 2 - lineWidth / 2
                judgeW = inChart.HScalePixel
                if topY - judgeTop + lineWidth < 4{
                    judgeH = 4
                }else{
                    judgeH = topY - judgeTop + 4 + lineWidth
                }
            }
            if mp.X >= judgeX && mp.X <= judgeX + judgeW && mp.Y >= judgeY && mp.Y <= judgeY + judgeH {

                return true
            }
        }
    }
    return false
}

/*
* 判断是否选中图形
* chart:图表
* mp:坐标
*/
func SelectShape(chart *FCView, mp FCPoint) {
    inChart := chart.GetChart()
    inChart.SelectShape = ""
    inChart.SelectShapeEx = ""
    candleHeight := GetCandleDivHeight(chart)
    volHeight := GetVolDivHeight(chart)
    indHeight := GetIndDivHeight(chart)
    index := GetChartIndex(chart, mp)
    if index != -1{
        if mp.Y >= candleHeight + volHeight && mp.Y <= candleHeight + volHeight + indHeight {
            if inChart.ShowIndicator == "MACD" {
                if SelectLines(chart, mp, 2, inChart.Allmacdarr, index) {
                    inChart.SelectShape = inChart.ShowIndicator
                    inChart.SelectShapeEx = "MACD"
                }
                if SelectLines(chart, mp, 2, inChart.Alldifarr, index) {
                    inChart.SelectShape = inChart.ShowIndicator
                    inChart.SelectShapeEx = "DIF"
                }else if SelectLines(chart, mp, 2, inChart.Alldeaarr, index) {
                    inChart.SelectShape = inChart.ShowIndicator
                    inChart.SelectShapeEx = "DEA"
                }
            } else if inChart.ShowIndicator == "KDJ" {
                if SelectLines(chart, mp, 2, inChart.KdjK, index) {
                    inChart.SelectShape = inChart.ShowIndicator
                    inChart.SelectShapeEx = "K"
                }else if SelectLines(chart, mp, 2, inChart.KdjD, index) {
                    inChart.SelectShape = inChart.ShowIndicator
                    inChart.SelectShapeEx = "D"
                } else if SelectLines(chart, mp, 2, inChart.KdjJ, index) {
                    inChart.SelectShape = inChart.ShowIndicator
                    inChart.SelectShapeEx = "J"
                }
            } else if inChart.ShowIndicator == "RSI" {
                if SelectLines(chart, mp, 2, inChart.Rsi1, index) {
                    inChart.SelectShape = inChart.ShowIndicator
                    inChart.SelectShapeEx = "6"
                }else if SelectLines(chart, mp, 2, inChart.Rsi2, index) {
                    inChart.SelectShape = inChart.ShowIndicator
                    inChart.SelectShapeEx = "12"
                } else if SelectLines(chart, mp, 2, inChart.Rsi3, index) {
                    inChart.SelectShape = inChart.ShowIndicator
                    inChart.SelectShapeEx = "24"
                }
            }else if inChart.ShowIndicator == "BIAS" {
                if SelectLines(chart, mp, 2, inChart.Bias1, index) {
                    inChart.SelectShape = inChart.ShowIndicator
                    inChart.SelectShapeEx = "1"
                }else if SelectLines(chart, mp, 2, inChart.Bias2, index) {
                    inChart.SelectShape = inChart.ShowIndicator
                    inChart.SelectShapeEx = "2"
                } else if SelectLines(chart, mp, 2, inChart.Bias3, index) {
                    inChart.SelectShape = inChart.ShowIndicator
                    inChart.SelectShapeEx = "3"
                }
            }else if inChart.ShowIndicator == "ROC" {
                if SelectLines(chart, mp, 2, inChart.Roc, index) {
                    inChart.SelectShape = inChart.ShowIndicator
                    inChart.SelectShapeEx = "ROC"
                }else if SelectLines(chart, mp, 2, inChart.RocMa, index) {
                    inChart.SelectShape = inChart.ShowIndicator
                    inChart.SelectShapeEx = "ROCMA"
                }
            } else if inChart.ShowIndicator == "WR" {
                if SelectLines(chart, mp, 2, inChart.Wr1, index) {
                    inChart.SelectShape = inChart.ShowIndicator
                    inChart.SelectShapeEx = "1"
                }else if SelectLines(chart, mp, 2, inChart.Wr2, index) {
                    inChart.SelectShape = "WR"
                    inChart.SelectShapeEx = "2"
                }
            } else if inChart.ShowIndicator == "CCI" {
                if SelectLines(chart, mp, 2, inChart.Cci, index) {
                    inChart.SelectShape = inChart.ShowIndicator
                }
            } else if inChart.ShowIndicator == "BBI" {
                if SelectLines(chart, mp, 2, inChart.Bbi, index) {
                    inChart.SelectShape = inChart.ShowIndicator
                }
            } else if inChart.ShowIndicator == "TRIX" {
                if SelectLines(chart, mp, 2, inChart.Trix, index) {
                    inChart.SelectShape = inChart.ShowIndicator
                    inChart.SelectShapeEx = "TRIX"
                }else if SelectLines(chart, mp, 2, inChart.TrixMa, index) {
                    inChart.SelectShape = inChart.ShowIndicator
                    inChart.SelectShapeEx = "TRIXMA"
                }
            } else if inChart.ShowIndicator == "DMA" {
                if SelectLines(chart, mp, 2, inChart.Dma1, index) {
                    inChart.SelectShape = inChart.ShowIndicator
                    inChart.SelectShapeEx = "DIF"
                }else if SelectLines(chart, mp, 2, inChart.Dma2, index) {
                    inChart.SelectShape = inChart.ShowIndicator
                    inChart.SelectShapeEx = "DIFMA"
                }
            }
        }else if mp.Y >= candleHeight && mp.Y <= candleHeight + volHeight {
            volY := GetChartY(chart, 1, inChart.Data[index].Volume)
            zeroY := GetChartY(chart, 1, 0)
            if mp.Y >= math.Min(volY, zeroY) && mp.Y <= math.Max(volY, zeroY) {
                inChart.SelectShape = "VOL"
            }
        }else if mp.Y >= 0 && mp.Y <= candleHeight {
            isTrend :=  false
            if inChart.Cycle == "trend"{
                isTrend = true
            }
            if !isTrend {
                if inChart.MainIndicator == "BOLL" {
                    if SelectLines(chart, mp, 0, inChart.BollMid, index) {
                        inChart.SelectShape = inChart.MainIndicator
                        inChart.SelectShapeEx = "MID"
                    }else if SelectLines(chart, mp, 0, inChart.BollUp, index) {
                        inChart.SelectShape = inChart.MainIndicator
                        inChart.SelectShapeEx = "UP"
                    } else if SelectLines(chart, mp, 0, inChart.BollDown, index) {
                        inChart.SelectShape = inChart.MainIndicator
                        inChart.SelectShapeEx = "DOWN"
                    }
                } else if inChart.MainIndicator == "MA" {
                    if SelectLines(chart, mp, 0, inChart.Ma5, index) {
                        inChart.SelectShape = inChart.MainIndicator
                        inChart.SelectShapeEx = "5"
                    }else if SelectLines(chart, mp, 0, inChart.Ma10, index) {
                        inChart.SelectShape = inChart.MainIndicator
                        inChart.SelectShapeEx = "10"
                    }else if SelectLines(chart, mp, 0, inChart.Ma20, index) {
                        inChart.SelectShape = inChart.MainIndicator
                        inChart.SelectShapeEx = "20"
                    }else if SelectLines(chart, mp, 0, inChart.Ma30, index) {
                        inChart.SelectShape = inChart.MainIndicator
                        inChart.SelectShapeEx = "30"
                    }else if SelectLines(chart, mp, 0, inChart.Ma120, index) {
                        inChart.SelectShape = inChart.MainIndicator
                        inChart.SelectShapeEx = "120"
                    }else if SelectLines(chart, mp, 0, inChart.Ma250, index) {
                        inChart.SelectShape = inChart.MainIndicator
                        inChart.SelectShapeEx = "250"
                    }
                }
            }
            if inChart.SelectShape == "" {
                highY := GetChartY(chart, 0, inChart.Data[index].High)
                lowY := GetChartY(chart, 0, inChart.Data[index].Low)
                if isTrend {
                    if SelectLines(chart, mp, 0, inChart.CloseArr, index) {
                        inChart.SelectShape = "CANDLE"
                    }
                }else {
                    if mp.Y >= math.Min(lowY, highY) && mp.Y <= math.Max(lowY, highY) {
                        inChart.SelectShape = "CANDLE"
                    }
                }
            }
        }
        if len(inChart.Shapes) > 0 {
            for i := 0; i < len(inChart.Shapes); i++ {
                shape := inChart.Shapes[i]
                if shape.LeftOrRight {
                    if SelectLines(chart, mp, shape.DivIndex, shape.Datas, index) {
                        inChart.SelectShape = shape.ShapeName
                        break
                    }
                } else {
                    if SelectLinesInRight(chart, mp, shape.DivIndex, shape.Datas, index) {
                        inChart.SelectShape = shape.ShapeName
                        break
                    }
                }
            }
        }
    }
}

/*
* 鼠标点击实现方法
* view: 图层
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
* clicks:点击次数
*/
func OnClickDefault(view *FCView, firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint, clicks int){
    if view.ViewType == "tabbutton" {
        tabView := view.GetParent()
        intTabView := tabView.GetTabView()
        if len(intTabView.TabPages) > 0{
            for i := 0; i < len(intTabView.TabPages); i++ {
                inTabPage := intTabView.TabPages[i].GetTabPage()
                if inTabPage.GetHeaderButton() == view {
                    SelectTabPage(tabView, intTabView.TabPages[i])
                    break
                }
            }
        }
        InvalidateView(tabView)
    }else if view.ViewType == "radiobutton" {
        ClickRadioButton(view, firstPoint)
        Invalidate(view.GetPaint())
    }else if view.ViewType == "checkbox" {
        ClickCheckBox(view, firstPoint)
        InvalidateView(view.GetParent())
    }else if view.ViewType == "menuitem"{
	    ClickMenuItem(view)
	}else if view.ViewType == "combobox"{
		ClickComboBox(view)
    }
}

/*
* 重绘背景的实现方法
* view:视图
* paint:绘图对象
* clipRect:裁剪区域
*/
func OnPaintDefault(view *FCView, paint *FCPaint, clipRect FCRect) {
    if view.OnPaint != nil{
        view.OnPaint(view, paint, clipRect)
        return
    }
    if view.ViewType == "chart"{
        DrawChart(view, paint, clipRect)
    }else if view.ViewType == "div" || view.ViewType == "layout" || view.ViewType == "tabpage" {
        DrawDiv(view, paint, clipRect)
    }else if view.ViewType == "grid" {
        DrawDiv(view, paint, clipRect)
        DrawGrid(view, paint, clipRect)
    }else if view.ViewType == "tree" {
        DrawDiv(view, paint, clipRect)
        DrawTree(view, paint, clipRect)
    }else if view.ViewType == "calendar"{
        DrawCalendar(view, paint)
    }else if view.ViewType == "label" {
        if view.TextColor != "none" {
            tSize := paint.TextSize(view.Text, view.Font)
            paint.DrawText(view.Text, view.TextColor, view.Font, 0, (view.Size.Cy - tSize.Cy) / 2)
        }
    }else if view.ViewType == "radiobutton" {
        DrawRadioButton(view, paint, clipRect)
    }else if view.ViewType == "checkbox" {
        DrawCheckBox(view, paint, clipRect)
    }else if view.ViewType == "menuitem"{
		DrawMenuItem(view, paint, clipRect)
    }else if view.ViewType == "combobox"{
		DrawComboBox(view, paint, clipRect)
    }else{
        DrawButton(view, paint, clipRect)
    }
}

/*
* 重绘边框的实现方法
* view:视图
* paint:绘图对象
* clipRect:裁剪区域
*/
func OnPaintBorderDefault(view *FCView, paint *FCPaint, clipRect FCRect) {
    if view.OnPaintBorder != nil{
        view.OnPaintBorder(view, paint, clipRect)
        return
    }
    if view.ViewType == "grid" {
        DrawGridScrollBar(view, paint, clipRect)
        DrawDivBorder(view, paint, clipRect)
    }else if view.ViewType == "tree"{
        DrawTreeScrollBar(view, paint, clipRect)
        DrawDivBorder(view, paint, clipRect)
    }else if view.ViewType == "div" || view.ViewType == "layout" || view.ViewType == "menu" {
        DrawDivScrollBar(view, paint, clipRect)
        DrawDivBorder(view, paint, clipRect)
    }else if view.ViewType == "tabpage" {
        DrawDivBorder(view, paint, clipRect)
    }else if view.ViewType == "tabview" {
        DrawTabViewBorder(view, paint, clipRect)
    } else if view.ViewType == "textbox" {
        DrawDivBorder(view, paint, clipRect)
    }
}

/*
*视图的鼠标移动方法
*view 视图
*mp 坐标
*buttons 按钮 0未按下 1左键 2右键
*clicks 点击次数
*delta 滚轮值
*/
func OnMouseMoveDefault(view *FCView, mp FCPoint, buttons int, clicks int, delta int){
    if view.OnMouseMove != nil{
        view.OnMouseMove(view, mp, buttons, clicks, delta)
        return
    }
	firstTouch := false
	secondTouch := false
	firstPoint := mp
	secondPoint := mp
	if buttons == 1{
		firstTouch = true
    }else if buttons == 2{
        secondTouch = true
    }
	if view.ViewType == "grid"{
		TouchMoveGrid(view, firstTouch, firstPoint, secondTouch, secondPoint)
		InvalidateView(view)
    }else if view.ViewType == "tree"{
		TouchMoveTree(view, firstTouch, firstPoint, secondTouch, secondPoint)
		InvalidateView(view)
	}else if view.ViewType == "chart"{
		TouchMoveChart(view, firstTouch, firstPoint, secondTouch, secondPoint)
		InvalidateView(view)
	}else if view.ViewType == "div" || view.ViewType =="layout" || view.ViewType =="menu"{
		TouchMoveDiv(view, firstTouch, firstPoint, secondTouch, secondPoint)
		InvalidateView(view)
	}else if view.ViewType == "button"{
		InvalidateView(view)
    }else if (view.ViewType == "menuitem"){
		TouchMoveMenuItem(view)
    }else{
        if view.AllowDrag && view.GetParent().IsNotEmpty && view.GetParent().ViewType == "split"{
            inSplit := view.GetParent().GetSplitDiv()
            if inSplit.GetSplitter() == view{
                if inSplit.LayoutStyle == "lefttoright" || inSplit.LayoutStyle == "righttoleft"{
                    view.GetPaint().Canvas.Get("style").Set("cursor", "ew-resize")
                }else{
                    view.GetPaint().Canvas.Get("style").Set("cursor", "ns-resize")
                }
            }
        }
        InvalidateView(view)
    }
}

/*
*视图的鼠标按下方法
*view 视图
*mp 坐标
*buttons 按钮 0未按下 1左键 2右键
*clicks 点击次数
*delta 滚轮值
*/
func OnMouseDownDefault(view *FCView, mp FCPoint, buttons int, clicks int, delta int){
    if view.OnMouseDown != nil{
        view.OnMouseDown(view, mp, buttons, clicks, delta)
        return
    }
	firstTouch := false
	secondTouch := false
	firstPoint := mp
	secondPoint := mp
	if buttons == 1{
		firstTouch = true
    }else if buttons == 2{
        secondTouch = true
    }
	if view.ViewType == "grid"{
		TouchDownGrid(view, firstTouch, firstPoint, secondTouch, secondPoint, clicks)
		InvalidateView(view)
    }else if view.ViewType == "tree"{
		TouchDownTree(view, firstTouch, firstPoint, secondTouch, secondPoint, clicks)
		InvalidateView(view)
    }else if view.ViewType == "div" || view.ViewType =="layout" || view.ViewType =="menu"{
		TouchDownDiv(view, firstTouch, firstPoint, secondTouch, secondPoint, clicks)
		InvalidateView(view)
    }else if view.ViewType == "button"{
		InvalidateView(view)
    }else if view.ViewType == "calendar"{
		ClickCalendar(view, firstPoint)
    }else if view.ViewType == "chart"{
		TouchDownChart(view, firstTouch, firstPoint, secondTouch, secondPoint)
		InvalidateView(view)
    }
}

/*
*视图的鼠标抬起方法
*view 视图
*mp 坐标
*buttons 按钮 0未按下 1左键 2右键
*clicks 点击次数
*delta 滚轮值
*/
func OnMouseUpDefault(view *FCView, mp FCPoint, buttons int, clicks int, delta int){
    if view.OnMouseUp != nil{
        view.OnMouseUp(view, mp, buttons, clicks, delta)
        return
    }
	firstTouch := false
	secondTouch := false
	firstPoint := mp
	secondPoint := mp
	if buttons == 1{
		firstTouch = true
    }else if buttons == 2{
        secondTouch = true
    }
	if view.ViewType == "grid"{
		TouchUpGrid(view, firstTouch, firstPoint, secondTouch, secondPoint, clicks)
    }else if view.ViewType == "tree"{
		TouchUpTree(view, firstTouch, firstPoint, secondTouch, secondPoint, clicks)
    }else if view.ViewType == "div" || view.ViewType =="layout" || view.ViewType =="menu"{
		TouchUpDiv(view, firstTouch, firstPoint, secondTouch, secondPoint, clicks)
    }else if view.ViewType == "chart"{
        chart := view.GetChart()
		chart.FirstTouchIndexCacheChart = -1
		chart.SecondTouchIndexCacheChart = -1
    }
    InvalidateView(view)
}

/*
*视图的鼠标滚动方法
*view 视图
*mp 坐标
*buttons 按钮 0未按下 1左键 2右键
*clicks 点击次数
*delta 滚轮值
*/
func OnMouseWheelDefault(view *FCView, mp FCPoint, buttons int, clicks int, delta int){
    if view.OnMouseWheel != nil{
        view.OnMouseWheel(view, mp, buttons, clicks, delta)
        return
    }
	if view.ViewType == "grid"{
		TouchWheelGrid(view, delta)
		InvalidateView(view)
    }else if view.ViewType == "tree"{
		TouchWheelTree(view, delta)
		InvalidateView(view)
    }else if view.ViewType == "div" || view.ViewType =="layout" || view.ViewType =="menu"{
		TouchWheelDiv(view, delta)
		InvalidateView(view)
    }else if view.ViewType == "chart"{
		if delta < 0{
			ZoomOutChart(view)
        }else if delta > 0{
			ZoomInChart(view)
        }
		InvalidateView(view)
    }
}

/*
*视图的鼠标按下方法
*view 视图
*firstTouch:是否第一次触摸
*firstPoint:第一次触摸的坐标
*secondTouch:是否第二次触摸
*secondPoint:第二次触摸的坐标
*/
func OnTouchBeginDefault(view *FCView, firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint){
    if view.OnTouchBegin != nil{
        view.OnTouchBegin(view, firstTouch, firstPoint, secondTouch, secondPoint)
        return
    }
	if view.ViewType == "grid"{
		TouchDownGrid(view, firstTouch, firstPoint, secondTouch, secondPoint, 1)
		InvalidateView(view)
    }else if view.ViewType == "tree"{
		TouchDownTree(view, firstTouch, firstPoint, secondTouch, secondPoint, 1)
		InvalidateView(view)
    }else if view.ViewType == "div" || view.ViewType =="layout" || view.ViewType =="menu"{
		TouchDownDiv(view, firstTouch, firstPoint, secondTouch, secondPoint, 1)
		InvalidateView(view)
    }else if view.ViewType == "button"{
		InvalidateView(view)
    }else if view.ViewType == "calendar"{
		ClickCalendar(view, firstPoint)
    }else if view.ViewType == "chart"{
		TouchDownChart(view, firstTouch, firstPoint, secondTouch, secondPoint)
		InvalidateView(view)
    }
}

/*
*视图的触摸移动方法
*view 视图
*firstTouch:是否第一次触摸
*firstPoint:第一次触摸的坐标
*secondTouch:是否第二次触摸
*secondPoint:第二次触摸的坐标
*/
func OnTouchMoveDefault(view *FCView, firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint){
    if view.OnTouchMove != nil{
        view.OnTouchMove(view, firstTouch, firstPoint, secondTouch, secondPoint)
        return
    }
    if view.ViewType == "grid"{
		TouchMoveGrid(view, firstTouch, firstPoint, secondTouch, secondPoint)
		InvalidateView(view)
    }else if view.ViewType == "tree"{
		TouchMoveTree(view, firstTouch, firstPoint, secondTouch, secondPoint)
		InvalidateView(view)
	}else if view.ViewType == "chart"{
		TouchMoveChart(view, firstTouch, firstPoint, secondTouch, secondPoint)
		InvalidateView(view)
	}else if view.ViewType == "div" || view.ViewType =="layout" || view.ViewType =="menu"{
		TouchMoveDiv(view, firstTouch, firstPoint, secondTouch, secondPoint)
		InvalidateView(view)
	}else if view.ViewType == "button"{
		InvalidateView(view)
    }else if (view.ViewType == "menuitem"){
		TouchMoveMenuItem(view)
    }else{
        InvalidateView(view)
    }
}

/*
*视图的触摸抬起方法
*view 视图
*firstTouch:是否第一次触摸
*firstPoint:第一次触摸的坐标
*secondTouch:是否第二次触摸
*secondPoint:第二次触摸的坐标
*/
func OnTouchEndDefault(view *FCView, firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint){
    if view.OnTouchEnd != nil{
        view.OnTouchEnd(view, firstTouch, firstPoint, secondTouch, secondPoint)
        return
    }
    if view.ViewType == "grid"{
		TouchUpGrid(view, firstTouch, firstPoint, secondTouch, secondPoint, 1)
    }else if view.ViewType == "tree"{
		TouchUpTree(view, firstTouch, firstPoint, secondTouch, secondPoint, 1)
    }else if view.ViewType == "div" || view.ViewType =="layout" || view.ViewType =="menu"{
		TouchUpDiv(view, firstTouch, firstPoint, secondTouch, secondPoint, 1)
    }else if view.ViewType == "chart"{
        chart := view.GetChart()
		chart.FirstTouchIndexCacheChart = -1
		chart.SecondTouchIndexCacheChart = -1
    }
    InvalidateView(view)
}

/*
* 键盘按下方法
*/
func OnKeyDownDefault(view *FCView, key int){
    if view.OnKeyDown != nil{
        view.OnKeyDown(view, key)
        return
    }
}

/*
* 键盘抬起方法
*/
func OnKeyUpDefault(view *FCView, key int){
    if view.OnKeyUp != nil{
        view.OnKeyUp(view, key)
        return
    }
}

/*
* 重绘视图
* views:视图集合
* paint:绘图对象
* rect:区域
*/
func RenderViews(views []*FCView, paint *FCPaint, rect FCRect) {
    viewsSize := len(views)
    if viewsSize > 0{
        for i := 0; i < viewsSize; i++ {
            view := views[i]
            if !rect.IsNotEmpty {
                noneRect := CreateRect(0, 0, 0, 0)
                noneRect.IsNotEmpty = false
                if len(view.Views) > 0 {
                    subViewsSize := len(view.Views)
                    if subViewsSize > 0 {
                        RenderViews(view.Views, paint, noneRect)
                    }
                }
                view.ClipRect = noneRect
                continue
            }
            if !view.TopMost && IsPaintVisible(view) {
                clx := ClientX(view)
                cly := ClientY(view)
                DrawRect := CreateRect(0, 0, view.Size.Cx, view.Size.Cy)
                clipRect := CreateRect(clx, cly, clx + view.Size.Cx, cly + view.Size.Cy)
                destRect := CreateRect(0, 0, 0, 0)
                if GetIntersectRect(&destRect, rect, clipRect) > 0{
                    view.ClipRect = destRect
                    paint.Save();
                    paint.SetOffset(clx, cly)
                    paint.SetClip(destRect.Left - clx, destRect.Top - cly, destRect.Right - clx, destRect.Bottom - cly)
                    if paint.OnPaint != nil{
                        paint.OnPaint(view, paint, DrawRect)
                    }else{
                        OnPaintDefault(view, paint, DrawRect)
                    }
                    if len(view.Views) > 0 {
                        subViewsSize := len(view.Views)
                        if subViewsSize > 0 {
                            RenderViews(view.Views, paint, destRect)
                        }
                    }
                    paint.SetOffset(clx, cly)
                    if paint.OnPaintBorder != nil{
                        paint.OnPaintBorder(view, paint, DrawRect)
                    }else{
                        OnPaintBorderDefault(view, paint, DrawRect)
                    }
                    paint.Restore();
                } else {
                    noneRect := CreateRect(0, 0, 0, 0)
                    noneRect.IsNotEmpty = false
                    if len(view.Views) > 0 {
                        subViewsSize := len(view.Views)
                        if subViewsSize > 0 {
                            RenderViews(view.Views, paint, noneRect)
                        }
                    }
                    view.ClipRect = noneRect
                }
            }
        }
        for i := 0; i < viewsSize; i++ {
            view := views[i]
            if !rect.IsNotEmpty {
                noneRect := CreateRect(0, 0, 0, 0)
                noneRect.IsNotEmpty = false
                if len(view.Views) > 0 {
                    subViewsSize := len(view.Views)
                    if subViewsSize > 0 {
                        RenderViews(view.Views, paint, noneRect)
                    }
                }
                view.ClipRect = noneRect
                continue
            }
            if view.TopMost && IsPaintVisible(view) {
                clx := ClientX(view)
                cly := ClientY(view)
                DrawRect := CreateRect(0, 0, view.Size.Cx, view.Size.Cy)
                clipRect := CreateRect(clx, cly, clx + view.Size.Cx, cly + view.Size.Cy)
                destRect := CreateRect(0, 0, 0, 0)
                if GetIntersectRect(&destRect, rect, clipRect) > 0{ 
                    view.ClipRect = destRect
                    paint.Save();
                    paint.SetOffset(clx, cly)
                    paint.SetClip(destRect.Left - clx, destRect.Top - cly, destRect.Right - clx, destRect.Bottom - cly)
                    if paint.OnPaint != nil{
                        paint.OnPaint(view, paint, DrawRect)
                    }else{
                        OnPaintDefault(view, paint, DrawRect)
                    }
                    if len(view.Views) > 0 {
                        subViewsSize := len(view.Views)
                        if subViewsSize > 0 {
                            RenderViews(view.Views, paint, destRect)
                        }
                    }
                    paint.SetOffset(clx, cly)
                    paint.SetClip(destRect.Left - clx, destRect.Top - cly, destRect.Right - clx, destRect.Bottom - cly)
                    if paint.OnPaintBorder != nil{
                        paint.OnPaintBorder(view, paint, DrawRect)
                    }else{
                        OnPaintBorderDefault(view, paint, DrawRect)
                    }
                    paint.Restore();
                } else {
                    noneRect := CreateRect(0, 0, 0, 0)
                    noneRect.IsNotEmpty = false
                    if len(view.Views) > 0 {
                        subViewsSize := len(view.Views)
                        if subViewsSize > 0 {
                            RenderViews(view.Views, paint, noneRect)
                        }
                    }
                    view.ClipRect = noneRect
                }
            }
        }
    }
}

/*
*鼠标按下方法
*mp 坐标
*buttons 按钮 0未按下 1左键 2右键
*clicks 点击次数
*delta 滚轮值
*paint 绘图对象
*/
func HandleMouseDown(mp FCPoint, buttons int, clicks int, delta int, paint *FCPaint){
    if clicks == 2{
		paint.IsDoubleClick = true
    }else{
		paint.IsDoubleClick = false
    }
	paint.CancelClick = false
	paint.TouchDownPoint = mp
	topViews := paint.Views
	touchDownView := FindView(mp, topViews)	
    paint.SetTouchDownView(touchDownView)
	if touchDownView.IsNotEmpty{
        CheckShowMenu(paint)
        paint.SetFocusedView(touchDownView)
		cmpPoint := CreatePoint(mp.X - ClientX(touchDownView), mp.Y - ClientY(touchDownView))
        if paint.OnMouseDown != nil{
            paint.OnMouseDown(touchDownView, cmpPoint, buttons, clicks, 0)
        }else{
            OnMouseDownDefault(touchDownView, cmpPoint, buttons, clicks, 0)
        }
        if touchDownView.AllowResize{
            touchDownView.ResizePoint = GetResizeState(touchDownView, cmpPoint)
            if touchDownView.ResizePoint != -1 {
                touchDownView.StartRect = CreateRect(touchDownView.Location.X, touchDownView.Location.Y, touchDownView.Location.X + touchDownView.Size.Cx,
                    touchDownView.Location.Y + touchDownView.Size.Cy)
            }
        }
    }
    ShowOrHideInput(paint.Views)
}

/*
*鼠标移动方法
*mp 坐标
*buttons 按钮 0未按下 1左键 2右键
*clicks 点击次数
*delta 滚轮值
*paint 绘图对象
*/
func HandleMouseMove(mp FCPoint, buttons int, clicks int, delta int, paint *FCPaint){
    touchDownView := paint.GetTouchDownView()
    draggingView := paint.GetDraggingView()
    if touchDownView.IsNotEmpty{
		cmpPoint := CreatePoint(mp.X - ClientX(touchDownView), mp.Y - ClientY(touchDownView))
        if paint.OnMouseMove != nil{
		    paint.OnMouseMove(touchDownView, cmpPoint, buttons, clicks, 0)
        }else{
            OnMouseMoveDefault(touchDownView, cmpPoint, buttons, clicks, 0)
        }
        if touchDownView.ResizePoint != -1{
            newBounds := CreateRect(touchDownView.StartRect.Left, touchDownView.StartRect.Top, touchDownView.StartRect.Right, touchDownView.StartRect.Bottom)
            newBounds = WindowResize(newBounds, touchDownView.ResizePoint, mp, paint.TouchDownPoint)
            touchDownView.Location = CreatePoint(newBounds.Left, newBounds.Top)
            touchDownView.Size = CreateSize(newBounds.Right - newBounds.Left, newBounds.Bottom - newBounds.Top)
            if touchDownView.GetParent().IsNotEmpty{
                InvalidateView(touchDownView.GetParent())
            }else{
                Invalidate(paint)
            }
        }else if touchDownView.AllowDrag{
			if math.Abs(mp.X - paint.TouchDownPoint.X) > 5 || math.Abs(mp.Y - paint.TouchDownPoint.Y) > 5{
				paint.DragBeginRect = CreateRect(touchDownView.Location.X, touchDownView.Location.Y, touchDownView.Location.X + touchDownView.Size.Cx, touchDownView.Location.Y + touchDownView.Size.Cy)
				paint.DragBeginPoint = CreatePoint(paint.TouchDownPoint.X, paint.TouchDownPoint.Y)
                paint.SetDraggingView(touchDownView)
                var pList []*FCView
				paint.TouchDownView = pList
            }
        }
    }else if draggingView.IsNotEmpty && buttons == 1{
		offsetX := mp.X - paint.DragBeginPoint.X
		offsetY := mp.Y - paint.DragBeginPoint.Y
		newBounds := CreateRect(paint.DragBeginRect.Left + offsetX, paint.DragBeginRect.Top + offsetY, paint.DragBeginRect.Right + offsetX, paint.DragBeginRect.Bottom + offsetY)
		draggingView.Location = CreatePoint(newBounds.Left, newBounds.Top)
		if draggingView.GetParent().IsNotEmpty && draggingView.GetParent().ViewType == "split"{
            inSplit := draggingView.GetParent().GetSplitDiv()
            inSplit.SplitPercent = -1
			ResetSplitLayoutDiv(draggingView.GetParent())
            if paint.OnUpdateView != nil{
                paint.OnUpdateView(draggingView.GetParent().Views)
            }else{
                UpdateViewDefault(draggingView.GetParent().Views)
            }
        }
		if draggingView.GetParent().IsNotEmpty{
			InvalidateView(draggingView.GetParent())
        }else{
			Invalidate(paint)
        }
    }else{
		topViews := paint.Views
		view := FindView(mp, topViews)
		cmpPoint := CreatePoint(mp.X - ClientX(view), mp.Y - ClientY(view))
		if view.IsNotEmpty{
			oldMouseMoveView := paint.GetTouchMoveView()
            paint.SetTouchMoveView(view)
			if oldMouseMoveView.IsNotEmpty && oldMouseMoveView != view{
                if oldMouseMoveView.OnMouseLeave != nil{
                    oldMouseMoveView.OnMouseLeave(oldMouseMoveView, cmpPoint, buttons, clicks, 0)
                }else if paint.OnMouseLeave != nil{
                    paint.OnMouseLeave(oldMouseMoveView, cmpPoint, buttons, clicks, 0)
                }
                InvalidateView(oldMouseMoveView)
            }
			if oldMouseMoveView.IsNotEmpty || oldMouseMoveView != view{
                if view.OnMouseEnter != nil{
                    view.OnMouseEnter(view, cmpPoint, buttons, clicks, 0)	
                }else if paint.OnMouseEnter != nil{
                    paint.OnMouseEnter(view, cmpPoint, buttons, clicks, 0)	
                }
                paint.Canvas.Get("style").Set("cursor", view.Cursor)
            }	
            if paint.OnMouseMove != nil{
                paint.OnMouseMove(view, cmpPoint, buttons, clicks, 0)
            }else{
                OnMouseMoveDefault(view, cmpPoint, buttons, clicks, 0)
            }
        }
    }
}

/*
*鼠标抬起方法
*mp 坐标
*buttons 按钮 0未按下 1左键 2右键
*clicks 点击次数
*delta 滚轮值
*paint 绘图对象
*/
func HandleMouseUp(mp FCPoint, buttons int, clicks int, delta int, paint *FCPaint){
	paint.IsDoubleClick = false
    touchDownView := paint.GetTouchDownView()
	if touchDownView.IsNotEmpty{
		cmpPoint := CreatePoint(mp.X - ClientX(touchDownView), mp.Y - ClientY(touchDownView))
		topViews := paint.Views
		view := FindView(mp, topViews)
		if view.IsNotEmpty && view == touchDownView{
			if !paint.CancelClick{
                if paint.OnClick != nil{
                    paint.OnClick(touchDownView, true, cmpPoint, false, cmpPoint, clicks)
                }else{
                    OnClickDefault(touchDownView, true, cmpPoint, false, cmpPoint, clicks)
                }
            }	
        }
		if touchDownView.IsNotEmpty{
			mouseDownView := paint.GetTouchDownView()
            mouseDownView.ResizePoint = -1
            var pList[] *FCView
            paint.TouchDownView = pList
            var pList2[] *FCView
            paint.TouchMoveView = pList2
            if paint.OnMouseUp != nil{
			    paint.OnMouseUp(mouseDownView, cmpPoint, buttons, clicks, 0)
            }else{
                OnMouseUpDefault(mouseDownView, cmpPoint, buttons, clicks, 0)
            }
        }
    }
    var pList2[] *FCView
    paint.DraggingView = pList2
}

/*
*鼠标滚动方法
*mp 坐标
*buttons 按钮 0未按下 1左键 2右键
*clicks 点击次数
*delta 滚轮值
*paint 绘图对象
*/
func HandleMouseWheel(mp FCPoint, buttons int, clicks int, delta int, paint *FCPaint){
	topViews := paint.Views
	view := FindView(mp, topViews)
	if view.IsNotEmpty{
		cmpPoint := CreatePoint(mp.X - ClientX(view), mp.Y - ClientY(view))
        if paint.OnMouseWheel != nil{
            paint.OnMouseWheel(view, cmpPoint, buttons, clicks, delta)
        }else{
            OnMouseWheelDefault(view, cmpPoint, buttons, clicks, delta)
        }
    }
}

/*
*处理触摸按下的事件
*firstTouch:是否第一次触摸
*firstPoint:第一次触摸的坐标
*secondTouch:是否第二次触摸
*secondPoint:第二次触摸的坐标
*paint 绘图对象
*/
func HandleTouchBegin(firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint, paint *FCPaint){
    paint.CancelClick = false
    mp := firstPoint
    paint.TouchDownPoint = mp
	topViews := paint.Views
	touchDownView := FindView(mp, topViews)
    paint.SetTouchDownView(touchDownView)
	if touchDownView.IsNotEmpty{
        CheckShowMenu(paint)
        paint.SetFocusedView(touchDownView)
        clx := ClientX(touchDownView);
		cly := ClientY(touchDownView);
        paint.FirstTouch = firstTouch;
		paint.SecondTouch = secondTouch;
		paint.TouchFirstPoint = CreatePoint(firstPoint.X - clx, firstPoint.Y - cly)
		paint.TouchSecondPoint = CreatePoint(secondPoint.X - clx, secondPoint.Y - cly)
        if paint.OnTouchBegin != nil{
            paint.OnTouchBegin(touchDownView, paint.FirstTouch, paint.TouchFirstPoint, paint.SecondTouch, paint.TouchSecondPoint)
        }else{
            OnTouchBeginDefault(touchDownView, paint.FirstTouch, paint.TouchFirstPoint, paint.SecondTouch, paint.TouchSecondPoint)
        }
        if touchDownView.AllowResize{
            touchDownView.ResizePoint = GetResizeState(touchDownView, paint.TouchFirstPoint)
            if touchDownView.ResizePoint != -1 {
                touchDownView.StartRect = CreateRect(touchDownView.Location.X, touchDownView.Location.Y, touchDownView.Location.X + touchDownView.Size.Cx,
                    touchDownView.Location.Y + touchDownView.Size.Cy)
            }
        }
    }
    ShowOrHideInput(paint.Views)
}

/*
*处理触摸移动的事件
*firstTouch:是否第一次触摸
*firstPoint:第一次触摸的坐标
*secondTouch:是否第二次触摸
*secondPoint:第二次触摸的坐标
*paint 绘图对象
*/
func HandleTouchMove(firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint, paint *FCPaint){
    touchDownView := paint.GetTouchDownView()
    draggingView := paint.GetDraggingView()
    mp := CreatePoint(firstPoint.X, firstPoint.Y)
    if touchDownView.IsNotEmpty{
        clx := ClientX(touchDownView);
		cly := ClientY(touchDownView);
        paint.FirstTouch = firstTouch;
		paint.SecondTouch = secondTouch;
		paint.TouchFirstPoint = CreatePoint(firstPoint.X - clx, firstPoint.Y - cly)
		paint.TouchSecondPoint = CreatePoint(secondPoint.X - clx, secondPoint.Y - cly)
        if paint.OnTouchMove != nil{
		    paint.OnTouchMove(touchDownView, paint.FirstTouch, paint.TouchFirstPoint, paint.SecondTouch, paint.TouchSecondPoint)
        }else{
            OnTouchMoveDefault(touchDownView, paint.FirstTouch, paint.TouchFirstPoint, paint.SecondTouch, paint.TouchSecondPoint)
        }
        if touchDownView.ResizePoint != -1{
            newBounds := CreateRect(touchDownView.StartRect.Left, touchDownView.StartRect.Top, touchDownView.StartRect.Right, touchDownView.StartRect.Bottom)
            newBounds = WindowResize(newBounds, touchDownView.ResizePoint, mp, paint.TouchDownPoint)
            touchDownView.Location = CreatePoint(newBounds.Left, newBounds.Top)
            touchDownView.Size = CreateSize(newBounds.Right - newBounds.Left, newBounds.Bottom - newBounds.Top)
            if touchDownView.GetParent().IsNotEmpty{
                InvalidateView(touchDownView.GetParent())
            }else{
                Invalidate(paint)
            }
        }else if touchDownView.AllowDrag{
			if math.Abs(mp.X - paint.TouchDownPoint.X) > 5 || math.Abs(mp.Y - paint.TouchDownPoint.Y) > 5{
				paint.DragBeginRect = CreateRect(touchDownView.Location.X, touchDownView.Location.Y, touchDownView.Location.X + touchDownView.Size.Cx, touchDownView.Location.Y + touchDownView.Size.Cy)
				paint.DragBeginPoint = CreatePoint(paint.TouchDownPoint.X, paint.TouchDownPoint.Y)
                paint.SetDraggingView(touchDownView)
                var pList []*FCView
				paint.TouchDownView = pList
            }
        }else{
            paint.TouchDownPoint = CreatePoint(mp.X, mp.Y)
        }
    }else if draggingView.IsNotEmpty{
		offsetX := mp.X - paint.DragBeginPoint.X
		offsetY := mp.Y - paint.DragBeginPoint.Y
		newBounds := CreateRect(paint.DragBeginRect.Left + offsetX, paint.DragBeginRect.Top + offsetY, paint.DragBeginRect.Right + offsetX, paint.DragBeginRect.Bottom + offsetY)
		draggingView.Location = CreatePoint(newBounds.Left, newBounds.Top)
		if draggingView.GetParent().IsNotEmpty && draggingView.GetParent().ViewType == "split"{
			ResetSplitLayoutDiv(draggingView.GetParent())
            if paint.OnUpdateView != nil{
                paint.OnUpdateView(draggingView.GetParent().Views)
            }else{
                UpdateViewDefault(draggingView.GetParent().Views)
            }
        }
		if draggingView.GetParent().IsNotEmpty{
			InvalidateView(draggingView.GetParent())
        }else{
			Invalidate(paint)
        }
    }
}

/*
*处理触摸抬起的事件
*firstTouch:是否第一次触摸
*firstPoint:第一次触摸的坐标
*secondTouch:是否第二次触摸
*secondPoint:第二次触摸的坐标
*paint 绘图对象
*/
func HandleTouchEnd(firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint, paint *FCPaint){
    touchDownView := paint.GetTouchDownView()
	if touchDownView.IsNotEmpty{
        mp := paint.TouchDownPoint
		topViews := paint.Views
		view := FindView(mp, topViews)
        clicks := 1
        if(paint.IsDoubleClick){
            clicks = 2;
        }
		if view.IsNotEmpty && view == touchDownView{
			if !paint.CancelClick{
                cmpPoint := CreatePoint(mp.X - ClientX(touchDownView), mp.Y - ClientY(touchDownView))
                if paint.OnClick != nil{
                    paint.OnClick(touchDownView, true, cmpPoint, false, cmpPoint, clicks)
                }else{
                    OnClickDefault(touchDownView, true, cmpPoint, false, cmpPoint, clicks)
                }
            }	
        }
		if touchDownView.IsNotEmpty{
			mouseDownView := paint.GetTouchDownView()
            mouseDownView.ResizePoint = -1;
            var pList[] *FCView
            paint.TouchDownView = pList
            if paint.OnTouchEnd != nil{
			    paint.OnTouchEnd(mouseDownView, paint.FirstTouch, paint.TouchFirstPoint, paint.SecondTouch, paint.TouchSecondPoint)
            }else{
                OnTouchEndDefault(mouseDownView, paint.FirstTouch, paint.TouchFirstPoint, paint.SecondTouch, paint.TouchSecondPoint)
            }
        }
    }
    var pList2[] *FCView
    paint.DraggingView = pList2
}

/*
* 头部层
*/
type FCXmlNode struct {
    NodeName string //名称
    Content string //内容
    Children []*FCXmlNode //子节点
    IsNotEmpty bool
    Attributes map[string]string //属性
}

/*
* 初始化
*/
func CreateXmlNode()(*FCXmlNode){
    xmlNode := new(FCXmlNode)
    xmlNode.IsNotEmpty = true
    xmlNode.Attributes = make(map[string]string)
    return xmlNode
}

/*
* 设置属性
* view:视图
* node:xml节点
*/
func SetAttributeDefault(view *FCView, node *FCXmlNode) {
	if view.GetPaint().IsNotEmpty {
		if view.GetPaint().DefaultUIStyle == "dark" {
			view.BackColor = "rgb(0,0,0)"
			view.BorderColor = "rgb(100,100,100)"
			view.TextColor = "rgb(255,255,255)"
            view.ScrollBarColor = "rgb(100,100,100)"
		} else if view.GetPaint().DefaultUIStyle == "light" {
			view.BackColor = "rgb(255,255,255)"
			view.BorderColor = "rgb(150,150,150)"
			view.TextColor = "rgb(0,0,0)"
            view.ScrollBarColor = "rgb(200,200,200)"
		}
	}
    for key,value := range node.Attributes{
        name := strings.ToLower(key)
        if name == "location" {
            strs := strings.Split(value, ",")
            xStr := strs[0]
            yStr := strs[1]
            if strings.Contains(xStr, "%"){
                view.ExAttributes["leftstr"] = xStr
            }else{
                view.Location.X = ConvertToFloat64(xStr)
            }
            if strings.Contains(yStr, "%"){
                view.ExAttributes["topstr"] = yStr
            }else{
                view.Location.Y = ConvertToFloat64(yStr)
            }
		} else if name == "size" {
            strs := strings.Split(value, ",")
			xStr := strs[0]
            yStr := strs[1]
            if strings.Contains(xStr, "%"){
                view.ExAttributes["widthstr"] = xStr
            }else{
                view.Size.Cx = ConvertToFloat64(xStr)
            }
            if strings.Contains(yStr, "%"){
                view.ExAttributes["heightstr"] = yStr
            }else{
                view.Size.Cy = ConvertToFloat64(yStr)
            }
		} else if name == "text" {
			view.Text = value
		} else if name == "backcolor" {
			lowerStr := strings.ToLower(value)
			if strings.Contains(lowerStr, "rgb") {
				view.BackColor = value
			} else {
				view.BackColor = "none"
			}
		} else if name == "bordercolor" {
            lowerStr := strings.ToLower(value)
			if strings.Contains(lowerStr, "rgb") {
				view.BorderColor = value
			} else {
				view.BorderColor = "none"
			}
		} else if name == "textcolor" {
            lowerStr := strings.ToLower(value)
			if strings.Contains(lowerStr, "rgb") {
				view.TextColor = value
			} else {
				view.TextColor = "none"
			}
		} else if name == "layoutstyle"{
            if view.ViewType == "split"{
                view.GetSplitDiv().LayoutStyle = strings.ToLower(value)
            }else if view.ViewType == "layout"{
                view.GetLayoutDiv().LayoutStyle = strings.ToLower(value)
            }else if view.ViewType == "menu"{
                view.GetLayoutDiv().LayoutStyle = strings.ToLower(value)
            }
		} else if name == "align" {
			view.Align = strings.ToLower(value)
		} else if name == "cursor" {
			view.Cursor = strings.ToLower(value)
		} else if name == "vertical-align" {
			view.VerticalAlign = strings.ToLower(value)
		} else if name == "dock" {
			view.Dock = strings.ToLower(value)
		} else if name == "font" {
			view.Font = value
		} else if name == "headerheight" {
            if view.ViewType == "grid"{
                view.GetGrid().HeaderHeight = ConvertToFloat64(value)
            }else if view.ViewType == "tree"{
                view.GetTree().HeaderHeight = ConvertToFloat64(value)
            }
		} else if name == "cornerradius" {
            view.CornerRadius = ConvertToFloat64(value)
		}else if name == "borderwidth" {
            view.BorderWidth = ConvertToFloat64(value)
		}  else if name == "splitmode" {
			view.GetSplitDiv().SplitMode = strings.ToLower(value)
		}else if name == "autowrap" {
            if strings.ToLower(value) == "true"{
                view.GetLayoutDiv().AutoWrap = true
            }else{
                view.GetLayoutDiv().AutoWrap = false
            }
		} else if name == "name" {
			view.ViewName = value
		} else if name == "tabindex" {
            view.TabIndex = ConvertToInt(value)
        }else if name == "tabstop" {
            if strings.ToLower(value) == "true"{
                view.TabStop = true
            }else{
                view.TabStop = false
            }
        }else if name == "enabled"{
            if strings.ToLower(value) == "true"{
                view.Enabled = true
            }else{
                view.Enabled = false
            } 
		}else if name == "showvscrollbar"{
            if strings.ToLower(value) == "true"{
                view.ShowVScrollBar = true
            }else{
                view.ShowVScrollBar = false
            }
		} else if name == "showhscrollbar"{
            if strings.ToLower(value) == "true"{
                view.ShowHScrollBar = true
            }else{
                view.ShowHScrollBar = false
            }
		} else if name == "visible" {
            if strings.ToLower(value) == "true"{
                view.Visible = true
            }else{
                view.Visible = false
            }
		} else if name == "displayoffset" {
            if strings.ToLower(value) == "true"{
                view.DisplayOffset = true
            }else{
                view.DisplayOffset = false
            }
		} else if name == "checked" {
            if view.ViewType == "checkbox"{
                if strings.ToLower(value) == "true"{
                    view.GetCheckBox().Checked = true
                }else{
                    view.GetCheckBox().Checked = false
                }
            }else if view.ViewType == "radiobutton"{
                if strings.ToLower(value) == "true"{
                    view.GetRadioButton().Checked = true
                }else{
                    view.GetRadioButton().Checked = false
                }
            }
		} else if name == "buttonsize" {
            strs := strings.Split(value, ",")
            if view.ViewType == "checkbox"{
                view.GetCheckBox().ButtonSize = CreateSize(ConvertToFloat64(strs[0]), ConvertToFloat64(strs[1]))
            }else if view.ViewType == "radiobutton"{
                view.GetRadioButton().ButtonSize = CreateSize(ConvertToFloat64(strs[0]), ConvertToFloat64(strs[1]))
            }
		} else if name == "topmost" {
            if strings.ToLower(value) == "true"{
                view.TopMost = true
            }else{
                view.TopMost = false
            }
		} else if name == "selectedindex" {
            if view.ViewType == "combobox"{
			    view.GetComboBox().SelectedIndex = ConvertToInt(value)
            }
		} else if name == "src" {
			view.Src = value
		} else if name == "backimage"{
			view.BackImage = value
		} else if name == "groupname" {
			view.GetRadioButton().GroupName = value
		} else if name == "allowdragscroll" {
            if strings.ToLower(value) == "true"{
                view.AllowDragScroll = true
            }else{
                view.AllowDragScroll = false
            }
		} else if name == "allowpreviewsevent" {
            if strings.ToLower(value) == "true"{
                view.AllowPreviewsEvent = true
            }else{
                view.AllowPreviewsEvent = false
            }
		} else if name == "allowdrag" {
            if strings.ToLower(value) == "true"{
                view.AllowDrag = true
            }else{
                view.AllowDrag = false
            }
		} else if name == "allowresize" {
            if strings.ToLower(value) == "true"{
                view.AllowResize = true
            }else{
                view.AllowResize = false
            }
		} else if name == "Indent" {
			view.GetTree().Indent = ConvertToFloat64(value)
		} else if name == "showcheckbox" {
            if strings.ToLower(value) == "true"{
                view.GetTree().ShowCheckBox = true
            }else{
                view.GetTree().ShowCheckBox = false
            }
		} else if name == "padding" {
            strs := strings.Split(value, ",")
			view.Padding = CreatePadding(ConvertToFloat64(strs[0]), ConvertToFloat64(strs[1]), ConvertToFloat64(strs[2]), ConvertToFloat64(strs[3]));
		} else if name == "margin" {
            strs := strings.Split(value, ",")
			view.Margin = CreatePadding(ConvertToFloat64(strs[0]), ConvertToFloat64(strs[1]), ConvertToFloat64(strs[2]), ConvertToFloat64(strs[3]));
        } else if name == "hoveredcolor" {
            lowerStr := strings.ToLower(value)
			if strings.Contains(lowerStr, "rgb") {
				view.HoveredColor = value
			} else {
				view.HoveredColor = "none"
			}
		} else if name == "pushedcolor" {
            lowerStr := strings.ToLower(value)
			if strings.Contains(lowerStr, "rgb") {
				view.PushedColor = value
			} else {
				view.PushedColor = "none"
			}
		} else if name == "layout" {
            if view.ViewType == "tabview"{
			    view.GetTabView().Layout = value
            }
		} else if name == "width"{
            if strings.Contains(value, "%"){
                view.ExAttributes["widthstr"] = value
            }else{
                view.Size.Cx = ConvertToFloat64(value)
            }
        } else if name == "height"{
            if strings.Contains(value, "%"){
                view.ExAttributes["heightstr"] = value
            }else{
                view.Size.Cy = ConvertToFloat64(value)
            }
        } else if name == "left"{
            if strings.Contains(value, "%"){
                view.ExAttributes["leftstr"] = value
            }else{
                view.Location.X = ConvertToFloat64(value)
            }
        } else if name == "top"{
            if strings.Contains(value, "%"){
                view.ExAttributes["topstr"] = value
            }else{
                view.Location.Y = ConvertToFloat64(value)
            }
        }else{
            view.ExAttributes[name] = value
        }
    }
}

/*
* 读取Xml中的树节点
* tree 树
* parentNode 父节点
* xmlNode Xml节点
*/
func ReadTreeXmlNodeDefault(tree *FCView, parentNode *FCTreeNode, xmlNode *FCXmlNode) {
	treeNode := CreateTreeNode()
	treeNode.Value = xmlNode.Attributes["text"]
	AppendTreeNode(tree, treeNode, parentNode)
	for i := 0; i < len(xmlNode.Children); i++{
		child := xmlNode.Children[i]
		nodeName := strings.ToLower(child.NodeName)
		if nodeName == "node" {
			ReadTreeXmlNodeDefault(tree, treeNode, child)
		}
	}
}

/*
* 读取Xml
* paint 绘图对象
* node节点
* parent 父视图
*/
func ReadXmlNodeDefault(paint *FCPaint, node *FCXmlNode, parent *FCView) {
    for i := 0; i < len(node.Children); i++{
		child := node.Children[i]
		view := new(FCView)
        view.IsNotEmpty = false
        viewType := ""
		nodeName := strings.ToLower(child.NodeName)
		if nodeName == "div" || nodeName == "view" {
			viewType = child.Attributes["type"]
			if viewType == "splitlayout" {
				view = CreateView("split")
			}else if viewType == "layout" {
				view = CreateView("layout")
			}else if viewType == "tab" {
				view = CreateView("tabview")
			}else if viewType == "tabpage" {
				view = CreateView("tabpage")
			}else if viewType == "radio" {
				view = CreateView("radiobutton")
			}else if viewType == "text" || viewType == "range"|| viewType == "datetime"{
				view = CreateView("textbox")
			}else if viewType == "checkbox" {
				view = CreateView("checkbox")
			}else if viewType == "custom" {
                cid := child.Attributes["cid"]
				view = CreateView("div")
                view.ViewType = cid
			}else {
				view = CreateView("div")
			}
		}else if nodeName == "select" {
            view = CreateView("combobox")
        }else if nodeName == "input" {
			viewType = child.Attributes["type"]
			if viewType == "radio" {
				view = CreateView("radiobutton")
			}else if viewType == "text" || viewType == "range"|| viewType == "datetime" {
				view = CreateView("textbox")
			}else if viewType == "checkbox" {
				view = CreateView("checkbox")
			}else if viewType == "custom" {
                cid := child.Attributes["cid"]
				view = CreateView("button")
                view.ViewType = cid
			}else {
				view = CreateView("button")
			}
		}else if nodeName == "chart" {
			view = CreateView("chart")
		}else if nodeName == "calendar" {
			view = CreateView("calendar")
		}else if nodeName == "table" {
			view = CreateView("grid")
		} else if nodeName == "tree" {
			view = CreateView("tree")
		} else if nodeName == "label" {
			view = CreateView("label")
		}else {
			view = CreateView("custom")
		}
        view.SetPaint(paint)
        view.SetParent(parent)
		SetAttributeDefault(view, child)
        if viewType == "text" {
			CreateInputTextBox(view)
		}else if viewType == "range" {
			CreateInputTextBox(view)
		}
		if view.IsNotEmpty {
			if viewType == "tabpage" {
				tabButton := CreateView("button")
				tabButton.ViewType = "tabbutton";
                atrHeaderSize,ok := child.Attributes["headersize"]
                if ok {
                    strs := strings.Split(atrHeaderSize, ",")
                    tabButton.Size = CreateSize(ConvertToFloat64(strs[0]), ConvertToFloat64(strs[1]))
                }else{
                    tabButton.Size = CreateSize(100, 20);
                }
				if view.GetPaint().DefaultUIStyle == "dark" {
					tabButton.BackColor = "rgb(0,0,0)"
					tabButton.BorderColor = "rgb(100,100,100)"
					tabButton.TextColor = "rgb(255,255,255)"
				} else if view.GetPaint().DefaultUIStyle == "light" {
					tabButton.BackColor = "rgb(255,255,255)"
					tabButton.BorderColor = "rgb(150,150,150)"
					tabButton.TextColor = "rgb(0,0,0)"
				}
				tabButton.Text = view.Text;
				AddTabPage(view.GetParent(), view, tabButton);
			} else {
				if parent.IsNotEmpty {
                    parent.Views = append(parent.Views, view)
				} else {
					paint.Views = append(paint.Views, view)
				}
			}
			if viewType == "splitlayout" {
                atrDatum,ok := child.Attributes["datumsize"]
                if ok {
                    strs := strings.Split(atrDatum, ",")
                    view.Size = CreateSize(ConvertToFloat64(strs[0]), ConvertToFloat64(strs[1]))
                }
				splitter := CreateView("")
				if view.GetPaint().DefaultUIStyle == "dark" {
					splitter.BackColor = "rgb(100,100,100)"
				} else if view.GetPaint().DefaultUIStyle == "light" {
					splitter.BackColor = "rgb(150,150,150)"
				}
                canDragSplitter,ok2 := child.Attributes["candragsplitter"]
                if ok2 {
                    if canDragSplitter == "true"{
                        splitter.AllowDrag = true
                    }
                }
                AddViewToParent(splitter, view)
				view.GetSplitDiv().SetSplitter(splitter)
				splitterposition := child.Attributes["splitterposition"]
				splitStr := strings.Split(splitterposition, ",")
				if len(splitStr) >= 4 {
					splitRect := CreateRect(ConvertToFloat64(splitStr[0]), ConvertToFloat64(splitStr[1]), ConvertToFloat64(splitStr[2]), ConvertToFloat64(splitStr[3]))
					splitter.Location = CreatePoint(splitRect.Left, splitRect.Top)
					splitter.Size = CreateSize(splitRect.Right - splitRect.Left, splitRect.Bottom - splitRect.Top)
				} else {
					sSize := ConvertToFloat64(splitStr[1])
					sPosition := ConvertToFloat64(splitStr[0])
					if view.GetSplitDiv().LayoutStyle == "lefttoright" || view.GetSplitDiv().LayoutStyle == "righttoleft" {
						splitter.Location = CreatePoint(sPosition, 0)
						splitter.Size = CreateSize(sSize, view.Size.Cy)
					} else {
						splitter.Location = CreatePoint(0, sPosition)
						splitter.Size = CreateSize(view.Size.Cx, sSize)
					}
				}
				ReadXmlNodeDefault(paint, child, view)
				view.GetSplitDiv().SetFirstView(view.Views[1])
				view.GetSplitDiv().SetSecondView(view.Views[2])
				view.GetSplitDiv().OldSize = CreateSize(view.Size.Cx, view.Size.Cy)
				ResetSplitLayoutDiv(view);
			} else if viewType == "tab" {
				ReadXmlNodeDefault(paint, child, view);
                inTabView := view.GetTabView()
				if len(inTabView.TabPages) > 0 {
                    strSelectedIndex,ok := child.Attributes["selectedindex"]
                    if ok {
                        selectedIndex := ConvertToInt(strSelectedIndex)
                        if(selectedIndex >= 0 && selectedIndex < len(inTabView.TabPages)){
                            inTabView.TabPages[selectedIndex].Visible = true
                        }else{
                            inTabView.TabPages[len(inTabView.TabPages) - 1].Visible = true
                        }
                    }else{
					    inTabView.TabPages[len(inTabView.TabPages) - 1].Visible = true
                    }
				}
			} else if nodeName == "table" {
                for n := 0; n < len(child.Children); n++{
					tChild := child.Children[n];
					if tChild.NodeName == "tr" {
                        gridRow := CreateGridRow()
                        gridRow.IsNotEmpty = false
                        for j := 0; j < len(tChild.Children); j++{
							sunNodeName := strings.ToLower(tChild.Children[j].NodeName)
							if sunNodeName == "th" {
								gridColumn := CreateGridColumn()
                                if view.GetPaint().DefaultUIStyle == "light" {
									gridColumn.BackColor = "rgb(230,230,230)"
									gridColumn.BorderColor = "rgb(150,150,150)"
									gridColumn.TextColor = "rgb(0,0,0)"
								} else if view.GetPaint().DefaultUIStyle == "dark" {
									gridColumn.BackColor = "rgb(50,50,50)"
									gridColumn.BorderColor = "rgb(100,100,100)"
									gridColumn.TextColor = "rgb(255,255,255)"
								}
								gridColumn.Width = 100;
                                atrWidth,okW := tChild.Children[j].Attributes["width"]
                                if okW {
                                    if strings.Contains(atrWidth, "%"){
                                        gridColumn.WidthStr = atrWidth
                                    }else{
                                        gridColumn.Width = ConvertToFloat64(atrWidth)
                                    }
                                }
                                atrBackColor,okW2 := tChild.Children[j].Attributes["backcolor"]
                                if okW2 {
                                    gridColumn.BackColor = atrBackColor
                                }
                                atrTextColor,okW3 := tChild.Children[j].Attributes["textcolor"]
                                if okW3 {
                                    gridColumn.TextColor = atrTextColor
                                }
                                atrBorderColor,okW4 := tChild.Children[j].Attributes["bordercolor"]
                                if okW4 {
                                    gridColumn.BorderColor = atrBorderColor
                                }
                                atrFont,okW5 := tChild.Children[j].Attributes["font"]
                                if okW5 {
                                    gridColumn.Font = atrFont
                                }
								gridColumn.Text = tChild.Children[j].Attributes["text"]
								view.GetGrid().Columns = append(view.GetGrid().Columns, gridColumn)
							}else if sunNodeName == "td" {
                                if !gridRow.IsNotEmpty{
                                    gridRow = CreateGridRow()
                                    view.GetGrid().Rows = append(view.GetGrid().Rows, gridRow)
                                }
                                gridCell := CreateGridCell()
                                gridCell.Value = tChild.Children[j].Content
                                gridRow.Cells = append(gridRow.Cells, gridCell)
                            }
						}
					}
				}
			}else if nodeName == "tree" {
                treeColumn := CreateTreeColumn()
				view.GetTree().Columns = append(view.GetTree().Columns, treeColumn)
			    columnWidth := 0.0
                for n := 0; n < len(child.Children); n++{
					tChild := child.Children[n];
					if tChild.NodeName == "nodes" {
                        for j := 0; j < len(tChild.Children); j++{
							sunNodeName := strings.ToLower(tChild.Children[j].NodeName)
							if sunNodeName == "node" {
                                noneNode := CreateTreeNode()
                                noneNode.IsNotEmpty = false
                                ReadTreeXmlNodeDefault(view, noneNode, tChild.Children[j]);
                            }
                        }
                    }else if tChild.NodeName == "tr" {
                        for j := 0; j < len(tChild.Children); j++{
							sunNodeName := strings.ToLower(tChild.Children[j].NodeName)
							if sunNodeName == "th" {
                                atrWidth,okW := tChild.Children[j].Attributes["width"]
                                if okW {
                                    if strings.Contains(atrWidth, "%"){
                                        treeColumn.WidthStr = atrWidth
                                    }else{
                                       columnWidth += ConvertToFloat64(atrWidth)
                                    }
                                }
                            }
                        }
                    }
                }
                if columnWidth > 0 {
					treeColumn.Width = columnWidth
				}
            }else if view.ViewType == "textbox"{       		
            }else if nodeName == "calendar"{
                InitCalendar(view)
                cYear := GetYear(view, 2022)
                cMonth := cYear.Months[10]
                cDay := cMonth.Days[1]
                view.GetCalendar().SetSelectedDay(cDay)
                UpdateCalendar(view)
			}else if nodeName == "select"{
                newMenu := CreateView("menu")
                view.GetComboBox().SetDropDownMenu(newMenu)
				newMenu.GetMenu().SetComboBox(view)
				AddView(newMenu, paint)
                newMenu.Size.Cx = view.Size.Cx
                for n := 0; n < len(child.Children); n++{
					tChild := child.Children[n];
					if tChild.NodeName == "option" {
                        menuItem := CreateView("menuitem")
						AddMenuItem(menuItem, newMenu)
                        SetAttributeDefault(menuItem, tChild)
                    }
                }
                if len(newMenu.GetMenu().Items) > 0 {
                    strSelectedIndex,ok := child.Attributes["selectedindex"]
                    if ok {
                        selectedIndex := ConvertToInt(strSelectedIndex)
                        if(selectedIndex >= 0 && selectedIndex < len(newMenu.GetMenu().Items)){
                            view.GetComboBox().SelectedIndex = selectedIndex
							view.Text = newMenu.GetMenu().Items[selectedIndex].Text
                        }else{
                            view.GetComboBox().SelectedIndex = 0
							view.Text = newMenu.GetMenu().Items[0].Text
                        }
                    }else{
                        view.GetComboBox().SelectedIndex = 0
						view.Text = newMenu.GetMenu().Items[0].Text
                    }
				}
            }else {
                if view.ViewType != "chart"{
				    ReadXmlNodeDefault(paint, child, view)
                }
			}
		}
	}
}

/*
* 加载图形界面
* paint:绘图对象
* xml:Xml内容
*/
func RenderFaceCat(paint *FCPaint, xmlStr string) {
    decoder := xml.NewDecoder(strings.NewReader(xmlStr))
    rootNode := new(FCXmlNode)
    rootNode.IsNotEmpty = false
    var xmlNodes []*FCXmlNode
    var isBody = false
    for t, err := decoder.Token(); err == nil; t, err = decoder.Token() {
        if err != nil{
            fmt.Println(err)
            break
        }
        switch token := t.(type) {
            case xml.StartElement:
                name := token.Name.Local
                if(isBody){
                    xmlNode := CreateXmlNode()
                    xmlNode.NodeName = name
                    for _, attr := range token.Attr {
                        atrName := attr.Name.Local
                        atrValue := attr.Value
                        xmlNode.Attributes[atrName] = atrValue
                    }
                    lastNode := xmlNodes[len(xmlNodes) - 1]
                    lastNode.Children = append(lastNode.Children, xmlNode)
                    xmlNodes = append(xmlNodes, xmlNode)
                }else{
                    if name == "body"{
                        isBody = true
                        xmlNode := CreateXmlNode()
                        xmlNode.NodeName = name
                        rootNode = xmlNode
                        xmlNodes = append(xmlNodes, xmlNode)
                    }
                }
            case xml.CharData:
                if len(xmlNodes) > 0{
                    xmlNodes[len(xmlNodes) - 1].Content = string([]byte(token))
                }
            case xml.EndElement:
                name := token.Name.Local
                if name == "body"{
                        isBody = false
                }else{
                    if isBody{
                        if len(xmlNodes) > 0{
                            index := len(xmlNodes) - 1
                            xmlNodes = append(xmlNodes[:index], xmlNodes[index + 1:]...)
                        }
                    }
                }
        }
    }  
    if rootNode.IsNotEmpty{
        noneView := new(FCView)
        noneView.IsNotEmpty = false
        ReadXmlNodeDefault(paint, rootNode, noneView)
    }
    if paint.OnUpdateView != nil{
        paint.OnUpdateView(paint.Views)
    }else{
        UpdateViewDefault(paint.Views)
    }
	Invalidate(paint)
}

/*
 * 缩放Canvas
 */
func ScaleCanvas(paint *FCPaint){
    context := paint.Context
    canvas := paint.Canvas
    var window js.Value = js.Global().Get("window")
    devicePixelRatio := window.Get("devicePixelRatio").Float()
    canvas.Get("style").Set("width", ConvertFloat64ToStr(canvas.Get("width").Float()) + "px")
    canvas.Get("style").Set("height", ConvertFloat64ToStr(canvas.Get("height").Float()) + "px")
    canvas.Set("width", canvas.Get("width").Float() * devicePixelRatio)
    canvas.Set("height", canvas.Get("height").Float() * devicePixelRatio)
    context.Call("scale", devicePixelRatio, devicePixelRatio)
    paint.Size = CreateSize(canvas.Get("width").Float(), canvas.Get("height").Float())
    paint.Ratio = devicePixelRatio
}

/*
 * 给Canvas注册事件
 */
func RegisterCanvas(paint *FCPaint){
    canvas := paint.Canvas
    mouseDown := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
        if !paint.IsMobile{
            event := args[0]
            x := event.Get("clientX").Float()
            y := event.Get("clientY").Float()
            mp := CreatePoint(x, y)
            mp.X /= paint.ScaleFactorX
            mp.Y /= paint.ScaleFactorY
            newClickTime := time.Now().Unix()
            clicks := 1
            if newClickTime - paint.LastClickTime < 250{
                paint.IsDoubleClick = true
                paint.LastClickTime = 0
                clicks = 2
            }else{
                paint.IsDoubleClick = false
                paint.LastClickTime = newClickTime
            }
            HandleMouseDown(mp, 1, clicks, 0, paint);
        }
        return nil
    })
    canvas.Call("addEventListener", "mousedown", mouseDown)
    mouseUp := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
        if !paint.IsMobile{
            event := args[0]
            x := event.Get("clientX").Float()
            y := event.Get("clientY").Float()
            mp := CreatePoint(x, y)
            mp.X /= paint.ScaleFactorX
            mp.Y /= paint.ScaleFactorY
            clicks := 1
            if(paint.IsDoubleClick){
                clicks = 2;
            }
            HandleMouseUp(mp, 1, clicks, 0, paint);
        }
        return nil
    })
    canvas.Call("addEventListener", "mouseup", mouseUp)
    mouseMove := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
        if !paint.IsMobile{
            event := args[0]
            x := event.Get("clientX").Float()
            y := event.Get("clientY").Float()
            mp := CreatePoint(x, y)
            mp.X /= paint.ScaleFactorX
            mp.Y /= paint.ScaleFactorY
            if gPaint.GetTouchDownView().IsNotEmpty || gPaint.GetDraggingView().IsNotEmpty{
                HandleMouseMove(mp, 1, 1, 0, paint);
            }else{
                HandleMouseMove(mp, 0, 0, 0, paint);
            }
        }
        return nil
    })
    canvas.Call("addEventListener", "mousemove", mouseMove)
    mouseWheel := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
        if !paint.IsMobile{
            event := args[0]
            delta := int(event.Get("deltaY").Float())
            x := event.Get("clientX").Float()
            y := event.Get("clientY").Float()
            mp := CreatePoint(x, y)
            mp.X /= paint.ScaleFactorX
            mp.Y /= paint.ScaleFactorY
            HandleMouseWheel(mp, 0, 0, delta, paint);
        }
        return nil
    })
    canvas.Call("addEventListener", "mousewheel", mouseWheel)
    DOMMouseScroll := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
        if !paint.IsMobile{
            event := args[0]
            delta := int(event.Get("detail").Float())
            x := event.Get("clientX").Float()
            y := event.Get("clientY").Float()
            mp := CreatePoint(x, y)
            mp.X /= paint.ScaleFactorX
            mp.Y /= paint.ScaleFactorY
            HandleMouseWheel(mp, 0, 0, delta, paint);
        }
        return nil
    })
    canvas.Call("addEventListener", "DOMMouseScroll", DOMMouseScroll)
    touchStart := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
        if paint.IsMobile{
            firstTouch := false
            secondTouch := false
            firstPoint := CreatePoint(0, 0)
            secondPoint := CreatePoint(0, 0)
            event := args[0]
            fEvent := event.Get("touches").Get("0")
            sEvent := event.Get("touches").Get("1")
            if fEvent.String() != "<undefined>"{
                firstTouch = true
                firstPoint.X = fEvent.Get("clientX").Float()
                firstPoint.Y = fEvent.Get("clientY").Float()
                firstPoint.X /= paint.ScaleFactorX
                firstPoint.Y /= paint.ScaleFactorY
            }
            if sEvent.String() != "<undefined>"{
                secondTouch = true
                secondPoint.X = sEvent.Get("clientX").Float()
                secondPoint.Y = sEvent.Get("clientY").Float()
                secondPoint.X /= paint.ScaleFactorX
                secondPoint.Y /= paint.ScaleFactorY
            }
            newClickTime := time.Now().Unix()
            if newClickTime - paint.LastClickTime < 250{
                paint.IsDoubleClick = true
                paint.LastClickTime = 0
            }else{
                paint.IsDoubleClick = false
                paint.LastClickTime = newClickTime
            }
            HandleTouchBegin(firstTouch, firstPoint, secondTouch, secondPoint, paint)
        }
        return nil
    })
    canvas.Call("addEventListener", "touchstart", touchStart)
    touchMove := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
        if paint.IsMobile{
            firstTouch := false
            secondTouch := false
            firstPoint := CreatePoint(0, 0)
            secondPoint := CreatePoint(0, 0)
            event := args[0]
            fEvent := event.Get("touches").Get("0")
            sEvent := event.Get("touches").Get("1")
            if fEvent.String() != "<undefined>"{
                firstTouch = true
                firstPoint.X = fEvent.Get("clientX").Float()
                firstPoint.Y = fEvent.Get("clientY").Float()
                firstPoint.X /= paint.ScaleFactorX
                firstPoint.Y /= paint.ScaleFactorY
            }
            if sEvent.String() != "<undefined>"{
                secondTouch = true
                secondPoint.X = sEvent.Get("clientX").Float()
                secondPoint.Y = sEvent.Get("clientY").Float()
                secondPoint.X /= paint.ScaleFactorX
                secondPoint.Y /= paint.ScaleFactorY
            }
            HandleTouchMove(firstTouch, firstPoint, secondTouch, secondPoint, paint)
        }
        return nil
    })
    canvas.Call("addEventListener", "touchmove", touchMove)
    touchEnd := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
        if paint.IsMobile{
            HandleTouchEnd(paint.FirstTouch, paint.TouchFirstPoint, paint.SecondTouch, paint.TouchSecondPoint, paint)
        }
        return nil
    })
    canvas.Call("addEventListener", "touchend", touchEnd)
    var window js.Value = js.Global().Get("window")
    var document js.Value = js.Global().Get("document")
    resizeAll := js.FuncOf(func(this js.Value, args []js.Value) interface{} {
        paint.Canvas.Set("width", document.Get("documentElement").Get("clientWidth").Float())
        paint.Canvas.Set("height", document.Get("documentElement").Get("clientHeight").Float())
        ScaleCanvas(paint)
        UpdateViewDefault(paint.Views)
        Invalidate(paint)
        return nil
    })
    window.Call("addEventListener", "resize", resizeAll)
    window.Call("addEventListener", "orientationchange", resizeAll)
}

////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////

/*
* 重绘背景的实现方法
* view:视图
* paint:绘图对象
* clipRect:裁剪区域
*/
func OnPaint(view *FCView, paint *FCPaint, clipRect FCRect) {
    OnPaintDefault(view, paint, clipRect)
}

/*
* 重绘边框的实现方法
* view:视图
* paint:绘图对象
* clipRect:裁剪区域
*/
func OnPaintBorder(view *FCView, paint *FCPaint, clipRect FCRect) {
    OnPaintBorderDefault(view, paint, clipRect)
}

/*
*视图的鼠标移动方法
*view 视图
*mp 坐标
*buttons 按钮 0未按下 1左键 2右键
*clicks 点击次数
*delta 滚轮值
*/
func OnMouseMove(view *FCView, mp FCPoint, buttons int, clicks int, delta int){
    OnMouseMoveDefault(view, mp, buttons, clicks, delta)
}

/*
*视图的鼠标按下方法
*view 视图
*mp 坐标
*buttons 按钮 0未按下 1左键 2右键
*clicks 点击次数
*delta 滚轮值
*/
func OnMouseDown(view *FCView, mp FCPoint, buttons int, clicks int, delta int){
    if view.ViewType == "chart" {
        if len(view.GetChart().Data) == 0{
            return
        }
        if len(view.GetChart().AddingPlotChart) > 0 {
            AddPlotDefault(view, true, mp, false, mp)
            view.GetChart().AddingPlotChart = ""
            InvalidateView(view)
        } else {
            TouchDownChart(view, true, mp, false, mp)
            InvalidateView(view)
        }
    }else{
        OnMouseDownDefault(view, mp, buttons, clicks, delta)
    }
}

/*
*视图的鼠标抬起方法
*view 视图
*mp 坐标
*buttons 按钮 0未按下 1左键 2右键
*clicks 点击次数
*delta 滚轮值
*/
func OnMouseUp(view *FCView, mp FCPoint, buttons int, clicks int, delta int){
    OnMouseUpDefault(view, mp, buttons, clicks, delta)
}

/*
* 鼠标点击实现方法
* view: 图层
* firstTouch:是否第一次触摸
* firstPoint:第一次触摸的坐标
* secondTouch:是否第二次触摸
* secondPoint:第二次触摸的坐标
* clicks:点击次数
*/
func OnClick(view *FCView, firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint, clicks int){
    OnClickDefault(view, firstTouch, firstPoint, secondTouch, secondPoint, clicks)
    if view.ViewName == "Indicator" {
        if view.Text == "BOLL" || view.Text == "MA" {
            tChart.GetChart().MainIndicator = view.Text;
        } else {
            tChart.GetChart().ShowIndicator = view.Text;
        }
        CalcChartIndicator(tChart)
        tabView2 := view.GetParent().GetParent().GetParent()
        SelectTabPage(tabView2, tabView2.GetTabView().TabPages[0])
        Invalidate(view.GetPaint())
    } else if view.ViewName == "Plot" {
        tChart.GetChart().AddingPlotChart = view.Text;
        tabView3 := view.GetParent().GetParent().GetParent()
        SelectTabPage(tabView3, tabView3.GetTabView().TabPages[0])
        Invalidate(view.GetPaint())
    }
}

/*
* 鼠标滚动实现方法
* view:视图
* mp:坐标
* button:按钮
* clicks:点击次数
* delta:滚轮值
*/
func OnMouseWheel(view *FCView, mp FCPoint, buttons int, clicks int, delta int) {
    OnMouseWheelDefault(view, mp, buttons, clicks, delta)
}

/*
* 鼠标离开实现方法
* view:视图
* mp:坐标
* button:按钮
* clicks:点击次数
* delta:滚轮值
*/
func OnMouseLeave(view *FCView, mp FCPoint, buttons int, clicks int, delta int) {
    OnMouseWheelDefault(view, mp, buttons, clicks, delta)
}

/*
* 鼠标进入实现方法
* view:视图
* mp:坐标
* button:按钮
* clicks:点击次数
* delta:滚轮值
*/
func OnMouseEnter(view *FCView, mp FCPoint, buttons int, clicks int, delta int) {
    OnMouseWheelDefault(view, mp, buttons, clicks, delta)
}

/*
*视图的鼠标按下方法
*view 视图
*firstTouch:是否第一次触摸
*firstPoint:第一次触摸的坐标
*secondTouch:是否第二次触摸
*secondPoint:第二次触摸的坐标
*/
func OnTouchBegin(view *FCView, firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint){
    if view.ViewType == "chart" {
        mp := CreatePoint(firstPoint.X, firstPoint.Y)
        if len(view.GetChart().Data) == 0{
            return
        }
        if len(view.GetChart().AddingPlotChart) > 0 {
            AddPlotDefault(view, true, mp, false, mp)
            view.GetChart().AddingPlotChart = ""
            InvalidateView(view)
        } else {
            TouchDownChart(view, true, mp, false, mp)
            InvalidateView(view)
        }
    }else{
        OnTouchBeginDefault(view, firstTouch, firstPoint, secondTouch, secondPoint)
    }
}

/*
*视图的触摸移动方法
*view 视图
*firstTouch:是否第一次触摸
*firstPoint:第一次触摸的坐标
*secondTouch:是否第二次触摸
*secondPoint:第二次触摸的坐标
*/
func OnTouchMove(view *FCView, firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint){
    OnTouchMoveDefault(view, firstTouch, firstPoint, secondTouch, secondPoint)
}

/*
*视图的触摸抬起方法
*view 视图
*firstTouch:是否第一次触摸
*firstPoint:第一次触摸的坐标
*secondTouch:是否第二次触摸
*secondPoint:第二次触摸的坐标
*/
func OnTouchEnd(view *FCView, firstTouch bool, firstPoint FCPoint, secondTouch bool, secondPoint FCPoint){
    OnTouchEndDefault(view, firstTouch, firstPoint, secondTouch, secondPoint)
}

func getElementByID(id string) js.Value {
    return js.Global().Get("document").Call("getElementById", id)
}
 
func jsAlert() js.Value {
    return js.Global().Get("alert")
}

func getSecurityDatas()([]*SecurityData){
    var securityDatas []*SecurityData
    sData1 := new(SecurityData)
    sData1.Volume = 78469.756458
    sData1.Close = 15684.25
    sData1.High = 15965.01
    sData1.Low = 15272.69
    sData1.Open = 15297.22
    sData1.Date = 1605052800.0
    securityDatas = append(securityDatas, sData1)
    sData2 := new(SecurityData)
    sData2.Volume = 102196.366592
    sData2.Close = 16291.87
    sData2.High = 16340.71
    sData2.Low = 15440.65
    sData2.Open = 15684.26
    sData2.Date = 1605139200.0
    securityDatas = append(securityDatas, sData2)
    sData3 := new(SecurityData)
    sData3.Volume = 75691.891014
    sData3.Close = 16320.71
    sData3.High = 16480.01
    sData3.Low = 15952.36
    sData3.Open = 16291.86
    sData3.Date = 1605225600.0
    securityDatas = append(securityDatas, sData3)
    sData4 := new(SecurityData)
    sData4.Volume = 59116.357179
    sData4.Close = 16070.46
    sData4.High = 16327.0
    sData4.Low = 15670.01
    sData4.Open = 16320.05
    sData4.Date = 1605312000.0
    securityDatas = append(securityDatas, sData4)
    sData5 := new(SecurityData)
    sData5.Volume = 43596.851513
    sData5.Close = 15957.01
    sData5.High = 16180.01
    sData5.Low = 15774.73
    sData5.Open = 16069.57
    sData5.Date = 1605398400.0
    securityDatas = append(securityDatas, sData5)
    sData6 := new(SecurityData)
    sData6.Volume = 81300.685924
    sData6.Close = 16713.58
    sData6.High = 16880.01
    sData6.Low = 15864.01
    sData6.Open = 15957.01
    sData6.Date = 1605484800.0
    securityDatas = append(securityDatas, sData6)
    sData7 := new(SecurityData)
    sData7.Volume = 115192.02613
    sData7.Close = 17659.39
    sData7.High = 17858.83
    sData7.Low = 16538.01
    sData7.Open = 16713.09
    sData7.Date = 1605571200.0
    securityDatas = append(securityDatas, sData7)
    sData8 := new(SecurityData)
    sData8.Volume = 141984.264415
    sData8.Close = 17776.13
    sData8.High = 18476.94
    sData8.Low = 17222.01
    sData8.Open = 17659.39
    sData8.Date = 1605657600.0
    securityDatas = append(securityDatas, sData8)
    sData9 := new(SecurityData)
    sData9.Volume = 93009.571008
    sData9.Close = 17802.83
    sData9.High = 18179.81
    sData9.Low = 17335.66
    sData9.Open = 17777.76
    sData9.Date = 1605744000.0
    securityDatas = append(securityDatas, sData9)
    sData10 := new(SecurityData)
    sData10.Volume = 88423.028489
    sData10.Close = 18655.68
    sData10.High = 18815.23
    sData10.Low = 17740.05
    sData10.Open = 17802.82
    sData10.Date = 1605830400.0
    securityDatas = append(securityDatas, sData10)
    sData11 := new(SecurityData)
    sData11.Volume = 71308.137138
    sData11.Close = 18703.81
    sData11.High = 18965.91
    sData11.Low = 18308.59
    sData11.Open = 18655.67
    sData11.Date = 1605916800.0
    securityDatas = append(securityDatas, sData11)
    sData12 := new(SecurityData)
    sData12.Volume = 74492.806006
    sData12.Close = 18414.61
    sData12.High = 18750.01
    sData12.Low = 17699.8
    sData12.Open = 18703.81
    sData12.Date = 1606003200.0
    securityDatas = append(securityDatas, sData12)
    sData13 := new(SecurityData)
    sData13.Volume = 74179.661546
    sData13.Close = 18368.01
    sData13.High = 18766.01
    sData13.Low = 18000.01
    sData13.Open = 18413.89
    sData13.Date = 1606089600.0
    securityDatas = append(securityDatas, sData13)
    sData14 := new(SecurityData)
    sData14.Volume = 70126.693681
    sData14.Close = 19160.02
    sData14.High = 19410.0
    sData14.Low = 18207.99
    sData14.Open = 18368.02
    sData14.Date = 1606176000.0
    securityDatas = append(securityDatas, sData14)
    sData15 := new(SecurityData)
    sData15.Volume = 70760.56353
    sData15.Close = 18719.12
    sData15.High = 19444.01
    sData15.Low = 18570.01
    sData15.Open = 19160.01
    sData15.Date = 1606262400.0
    securityDatas = append(securityDatas, sData15)
    sData16 := new(SecurityData)
    sData16.Volume = 102420.321403
    sData16.Close = 17149.48
    sData16.High = 18915.04
    sData16.Low = 16188.01
    sData16.Open = 18718.84
    sData16.Date = 1606348800.0
    securityDatas = append(securityDatas, sData16)
    sData17 := new(SecurityData)
    sData17.Volume = 84036.578341
    sData17.Close = 17139.53
    sData17.High = 17457.63
    sData17.Low = 16438.09
    sData17.Open = 17149.48
    sData17.Date = 1606435200.0
    securityDatas = append(securityDatas, sData17)
    sData18 := new(SecurityData)
    sData18.Volume = 60835.734083
    sData18.Close = 17719.86
    sData18.High = 17880.5
    sData18.Low = 16865.57
    sData18.Open = 17139.54
    sData18.Date = 1606521600.0
    securityDatas = append(securityDatas, sData18)
    sData19 := new(SecurityData)
    sData19.Volume = 55329.026303
    sData19.Close = 18185.0
    sData19.High = 18360.06
    sData19.Low = 17517.01
    sData19.Open = 17719.85
    sData19.Date = 1606608000.0
    securityDatas = append(securityDatas, sData19)
    sData20 := new(SecurityData)
    sData20.Volume = 96227.350495
    sData20.Close = 19695.88
    sData20.High = 19777.04
    sData20.Low = 18185.0
    sData20.Open = 18185.01
    sData20.Date = 1606694400.0
    securityDatas = append(securityDatas, sData20)
    sData21 := new(SecurityData)
    sData21.Volume = 100331.141203
    sData21.Close = 18764.97
    sData21.High = 19888.01
    sData21.Low = 18350.0
    sData21.Open = 19695.88
    sData21.Date = 1606780800.0
    securityDatas = append(securityDatas, sData21)
    sData22 := new(SecurityData)
    sData22.Volume = 75848.875728
    sData22.Close = 19204.1
    sData22.High = 19342.01
    sData22.Low = 18330.01
    sData22.Open = 18764.97
    sData22.Date = 1606867200.0
    securityDatas = append(securityDatas, sData22)
    sData23 := new(SecurityData)
    sData23.Volume = 64987.682732
    sData23.Close = 19421.91
    sData23.High = 19598.01
    sData23.Low = 18867.21
    sData23.Open = 19204.09
    sData23.Date = 1606953600.0
    securityDatas = append(securityDatas, sData23)
    sData24 := new(SecurityData)
    sData24.Volume = 65481.220724
    sData24.Close = 18650.53
    sData24.High = 19527.01
    sData24.Low = 18565.32
    sData24.Open = 19422.35
    sData24.Date = 1607040000.0
    securityDatas = append(securityDatas, sData24)
    sData25 := new(SecurityData)
    sData25.Volume = 42922.758573
    sData25.Close = 19147.67
    sData25.High = 19177.01
    sData25.Low = 18500.01
    sData25.Open = 18650.52
    sData25.Date = 1607126400.0
    securityDatas = append(securityDatas, sData25)
    sData26 := new(SecurityData)
    sData26.Volume = 37043.101861
    sData26.Close = 19359.41
    sData26.High = 19420.01
    sData26.Low = 18857.01
    sData26.Open = 19147.67
    sData26.Date = 1607212800.0
    securityDatas = append(securityDatas, sData26)
    sData27 := new(SecurityData)
    sData27.Volume = 40833.661907
    sData27.Close = 19166.91
    sData27.High = 19420.92
    sData27.Low = 18902.89
    sData27.Open = 19358.68
    sData27.Date = 1607299200.0
    securityDatas = append(securityDatas, sData27)
    sData28 := new(SecurityData)
    sData28.Volume = 56080.515386
    sData28.Close = 18324.12
    sData28.High = 19294.85
    sData28.Low = 18200.01
    sData28.Open = 19166.91
    sData28.Date = 1607385600.0
    securityDatas = append(securityDatas, sData28)
    sData29 := new(SecurityData)
    sData29.Volume = 75498.213856
    sData29.Close = 18541.29
    sData29.High = 18639.58
    sData29.Low = 17650.01
    sData29.Open = 18324.12
    sData29.Date = 1607472000.0
    securityDatas = append(securityDatas, sData29)
    sData30 := new(SecurityData)
    sData30.Volume = 52890.685094
    sData30.Close = 18254.64
    sData30.High = 18557.33
    sData30.Low = 17911.13
    sData30.Open = 18541.3
    sData30.Date = 1607558400.0
    securityDatas = append(securityDatas, sData30)
    sData31 := new(SecurityData)
    sData31.Volume = 72610.734259
    sData31.Close = 18036.54
    sData31.High = 18292.74
    sData31.Low = 17572.34
    sData31.Open = 18254.82
    sData31.Date = 1607644800.0
    securityDatas = append(securityDatas, sData31)
    sData32 := new(SecurityData)
    sData32.Volume = 47592.761572
    sData32.Close = 18808.7
    sData32.High = 18948.67
    sData32.Low = 18020.71
    sData32.Open = 18036.54
    sData32.Date = 1607731200.0
    securityDatas = append(securityDatas, sData32)
    sData33 := new(SecurityData)
    sData33.Volume = 56560.831744
    sData33.Close = 19175.0
    sData33.High = 19411.01
    sData33.Low = 18711.13
    sData33.Open = 18808.7
    sData33.Date = 1607817600.0
    securityDatas = append(securityDatas, sData33)
    sData34 := new(SecurityData)
    sData34.Volume = 47257.211294
    sData34.Close = 19273.15
    sData34.High = 19349.01
    sData34.Low = 19000.01
    sData34.Open = 19175.0
    sData34.Date = 1607904000.0
    securityDatas = append(securityDatas, sData34)
    sData35 := new(SecurityData)
    sData35.Volume = 61792.483421
    sData35.Close = 19426.44
    sData35.High = 19570.01
    sData35.Low = 19050.01
    sData35.Open = 19273.7
    sData35.Date = 1607990400.0
    securityDatas = append(securityDatas, sData35)
    sData36 := new(SecurityData)
    sData36.Volume = 97061.040854
    sData36.Close = 21335.53
    sData36.High = 21560.01
    sData36.Low = 19278.61
    sData36.Open = 19426.44
    sData36.Date = 1608076800.0
    securityDatas = append(securityDatas, sData36)
    sData37 := new(SecurityData)
    sData37.Volume = 148769.444419
    sData37.Close = 22808.99
    sData37.High = 23699.71
    sData37.Low = 21233.01
    sData37.Open = 21335.53
    sData37.Date = 1608163200.0
    securityDatas = append(securityDatas, sData37)
    sData38 := new(SecurityData)
    sData38.Volume = 79646.144315
    sData38.Close = 23107.4
    sData38.High = 23285.19
    sData38.Low = 22350.01
    sData38.Open = 22797.16
    sData38.Date = 1608249600.0
    securityDatas = append(securityDatas, sData38)
    sData39 := new(SecurityData)
    sData39.Volume = 82430.712232
    sData39.Close = 23821.62
    sData39.High = 24171.48
    sData39.Low = 22750.01
    sData39.Open = 23107.4
    sData39.Date = 1608336000.0
    securityDatas = append(securityDatas, sData39)
    sData40 := new(SecurityData)
    sData40.Volume = 74797.201958
    sData40.Close = 23455.53
    sData40.High = 24295.01
    sData40.Low = 23060.01
    sData40.Open = 23821.61
    sData40.Date = 1608422400.0
    securityDatas = append(securityDatas, sData40)
    sData41 := new(SecurityData)
    sData41.Volume = 83424.441428
    sData41.Close = 22719.72
    sData41.High = 24102.78
    sData41.Low = 21815.01
    sData41.Open = 23455.55
    sData41.Date = 1608508800.0
    securityDatas = append(securityDatas, sData41)
    sData42 := new(SecurityData)
    sData42.Volume = 87033.13616
    sData42.Close = 23810.8
    sData42.High = 23837.11
    sData42.Low = 22353.41
    sData42.Open = 22719.89
    sData42.Date = 1608595200.0
    securityDatas = append(securityDatas, sData42)
    sData43 := new(SecurityData)
    sData43.Volume = 112830.021287
    sData43.Close = 23232.77
    sData43.High = 24100.01
    sData43.Low = 22810.01
    sData43.Open = 23810.8
    sData43.Date = 1608681600.0
    securityDatas = append(securityDatas, sData43)
    sData44 := new(SecurityData)
    sData44.Volume = 69013.844252
    sData44.Close = 23729.21
    sData44.High = 23794.44
    sData44.Low = 22703.43
    sData44.Open = 23232.4
    sData44.Date = 1608768000.0
    securityDatas = append(securityDatas, sData44)
    sData45 := new(SecurityData)
    sData45.Volume = 78024.251646
    sData45.Close = 24712.48
    sData45.High = 24789.87
    sData45.Low = 23434.74
    sData45.Open = 23729.0
    sData45.Date = 1608854400.0
    securityDatas = append(securityDatas, sData45)
    sData46 := new(SecurityData)
    sData46.Volume = 97806.523386
    sData46.Close = 26493.4
    sData46.High = 26867.04
    sData46.Low = 24500.01
    sData46.Open = 24712.48
    sData46.Date = 1608940800.0
    securityDatas = append(securityDatas, sData46)
    sData47 := new(SecurityData)
    sData47.Volume = 145880.8092
    sData47.Close = 26281.67
    sData47.High = 28422.01
    sData47.Low = 25700.01
    sData47.Open = 26493.41
    sData47.Date = 1609027200.0
    securityDatas = append(securityDatas, sData47)
    sData48 := new(SecurityData)
    sData48.Volume = 79408.740817
    sData48.Close = 27079.42
    sData48.High = 27500.01
    sData48.Low = 26101.01
    sData48.Open = 26281.55
    sData48.Date = 1609113600.0
    securityDatas = append(securityDatas, sData48)
    sData49 := new(SecurityData)
    sData49.Volume = 69255.341092
    sData49.Close = 27385.01
    sData49.High = 27410.01
    sData49.Low = 25880.01
    sData49.Open = 27079.43
    sData49.Date = 1609200000.0
    securityDatas = append(securityDatas, sData49)
    sData50 := new(SecurityData)
    sData50.Volume = 95356.067826
    sData50.Close = 28875.55
    sData50.High = 28996.01
    sData50.Low = 27320.01
    sData50.Open = 27385.01
    sData50.Date = 1609286400.0
    securityDatas = append(securityDatas, sData50)
    sData51 := new(SecurityData)
    sData51.Volume = 75491.419522
    sData51.Close = 28923.64
    sData51.High = 29300.01
    sData51.Low = 27850.01
    sData51.Open = 28875.56
    sData51.Date = 1609372800.0
    securityDatas = append(securityDatas, sData51)
    sData52 := new(SecurityData)
    sData52.Volume = 54134.113624
    sData52.Close = 29331.7
    sData52.High = 29600.01
    sData52.Low = 28624.58
    sData52.Open = 28923.64
    sData52.Date = 1609459200.0
    securityDatas = append(securityDatas, sData52)
    sData53 := new(SecurityData)
    sData53.Volume = 126100.088124
    sData53.Close = 32178.34
    sData53.High = 33300.01
    sData53.Low = 28946.54
    sData53.Open = 29331.71
    sData53.Date = 1609545600.0
    securityDatas = append(securityDatas, sData53)
    sData54 := new(SecurityData)
    sData54.Volume = 110771.806254
    sData54.Close = 33000.06
    sData54.High = 34778.12
    sData54.Low = 31963.0
    sData54.Open = 32176.46
    sData54.Date = 1609632000.0
    securityDatas = append(securityDatas, sData54)
    sData55 := new(SecurityData)
    sData55.Volume = 121030.155465
    sData55.Close = 31988.72
    sData55.High = 33600.01
    sData55.Low = 28130.01
    sData55.Open = 33000.06
    sData55.Date = 1609718400.0
    securityDatas = append(securityDatas, sData55)
    sData56 := new(SecurityData)
    sData56.Volume = 111890.475678
    sData56.Close = 33949.54
    sData56.High = 34360.01
    sData56.Low = 29900.01
    sData56.Open = 31989.76
    sData56.Date = 1609804800.0
    securityDatas = append(securityDatas, sData56)
    sData57 := new(SecurityData)
    sData57.Volume = 116093.037717
    sData57.Close = 36769.37
    sData57.High = 36939.22
    sData57.Low = 33288.01
    sData57.Open = 33949.54
    sData57.Date = 1609891200.0
    securityDatas = append(securityDatas, sData57)
    sData58 := new(SecurityData)
    sData58.Volume = 121506.449096
    sData58.Close = 39432.29
    sData58.High = 40365.01
    sData58.Low = 36300.01
    sData58.Open = 36769.37
    sData58.Date = 1609977600.0
    securityDatas = append(securityDatas, sData58)
    sData59 := new(SecurityData)
    sData59.Volume = 138625.042444
    sData59.Close = 40582.82
    sData59.High = 41950.01
    sData59.Low = 36500.01
    sData59.Open = 39432.49
    sData59.Date = 1610064000.0
    securityDatas = append(securityDatas, sData59)
    sData60 := new(SecurityData)
    sData60.Volume = 75785.989675
    sData60.Close = 40088.23
    sData60.High = 41380.01
    sData60.Low = 38720.01
    sData60.Open = 40586.97
    sData60.Date = 1610150400.0
    securityDatas = append(securityDatas, sData60)
    sData61 := new(SecurityData)
    sData61.Volume = 112638.990321
    sData61.Close = 38150.03
    sData61.High = 41350.01
    sData61.Low = 35111.12
    sData61.Open = 40088.23
    sData61.Date = 1610236800.0
    securityDatas = append(securityDatas, sData61)
    sData62 := new(SecurityData)
    sData62.Volume = 231175.583454
    sData62.Close = 35404.48
    sData62.High = 38264.75
    sData62.Low = 30420.01
    sData62.Open = 38150.03
    sData62.Date = 1610323200.0
    securityDatas = append(securityDatas, sData62)
    sData63 := new(SecurityData)
    sData63.Volume = 133948.161996
    sData63.Close = 34051.25
    sData63.High = 36628.01
    sData63.Low = 32531.01
    sData63.Open = 35410.38
    sData63.Date = 1610409600.0
    securityDatas = append(securityDatas, sData63)
    sData64 := new(SecurityData)
    sData64.Volume = 124477.924938
    sData64.Close = 37371.39
    sData64.High = 37850.01
    sData64.Low = 32380.01
    sData64.Open = 34049.16
    sData64.Date = 1610496000.0
    securityDatas = append(securityDatas, sData64)
    sData65 := new(SecurityData)
    sData65.Volume = 102950.399421
    sData65.Close = 39144.51
    sData65.High = 40100.01
    sData65.Low = 36701.24
    sData65.Open = 37371.39
    sData65.Date = 1610582400.0
    securityDatas = append(securityDatas, sData65)
    sData66 := new(SecurityData)
    sData66.Volume = 111365.804668
    sData66.Close = 36742.23
    sData66.High = 39747.77
    sData66.Low = 34538.89
    sData66.Open = 39145.22
    sData66.Date = 1610668800.0
    securityDatas = append(securityDatas, sData66)
    sData67 := new(SecurityData)
    sData67.Volume = 86348.441508
    sData67.Close = 35994.99
    sData67.High = 37950.01
    sData67.Low = 35357.81
    sData67.Open = 36737.44
    sData67.Date = 1610755200.0
    securityDatas = append(securityDatas, sData67)
    sData68 := new(SecurityData)
    sData68.Volume = 80157.737384
    sData68.Close = 35828.62
    sData68.High = 36852.51
    sData68.Low = 33850.01
    sData68.Open = 35994.99
    sData68.Date = 1610841600.0
    securityDatas = append(securityDatas, sData68)
    sData69 := new(SecurityData)
    sData69.Volume = 70693.90404
    sData69.Close = 36631.28
    sData69.High = 37469.84
    sData69.Low = 34800.01
    sData69.Open = 35825.0
    sData69.Date = 1610928000.0
    securityDatas = append(securityDatas, sData69)
    sData70 := new(SecurityData)
    sData70.Volume = 79596.541309
    sData70.Close = 35891.5
    sData70.High = 37850.01
    sData70.Low = 35844.07
    sData70.Open = 36622.47
    sData70.Date = 1611014400.0
    securityDatas = append(securityDatas, sData70)
    sData71 := new(SecurityData)
    sData71.Volume = 89368.432918
    sData71.Close = 35468.24
    sData71.High = 36415.32
    sData71.Low = 33400.01
    sData71.Open = 35901.95
    sData71.Date = 1611100800.0
    securityDatas = append(securityDatas, sData71)
    sData72 := new(SecurityData)
    sData72.Volume = 134548.811336
    sData72.Close = 30850.14
    sData72.High = 35600.01
    sData72.Low = 30071.01
    sData72.Open = 35468.24
    sData72.Date = 1611187200.0
    securityDatas = append(securityDatas, sData72)
    sData73 := new(SecurityData)
    sData73.Volume = 138345.853436
    sData73.Close = 32945.18
    sData73.High = 33826.54
    sData73.Low = 28850.01
    sData73.Open = 30852.0
    sData73.Date = 1611273600.0
    securityDatas = append(securityDatas, sData73)
    sData74 := new(SecurityData)
    sData74.Volume = 64595.297675
    sData74.Close = 32078.01
    sData74.High = 33456.01
    sData74.Low = 31390.17
    sData74.Open = 32950.01
    sData74.Date = 1611360000.0
    securityDatas = append(securityDatas, sData74)
    sData75 := new(SecurityData)
    sData75.Volume = 57978.047966
    sData75.Close = 32259.91
    sData75.High = 33071.01
    sData75.Low = 30900.01
    sData75.Open = 32078.01
    sData75.Date = 1611446400.0
    securityDatas = append(securityDatas, sData75)
    sData76 := new(SecurityData)
    sData76.Volume = 88499.236921
    sData76.Close = 32254.21
    sData76.High = 34875.01
    sData76.Low = 31910.01
    sData76.Open = 32259.46
    sData76.Date = 1611532800.0
    securityDatas = append(securityDatas, sData76)
    sData77 := new(SecurityData)
    sData77.Volume = 84866.207055
    sData77.Close = 32467.78
    sData77.High = 32921.89
    sData77.Low = 30837.38
    sData77.Open = 32254.2
    sData77.Date = 1611619200.0
    securityDatas = append(securityDatas, sData77)
    sData78 := new(SecurityData)
    sData78.Volume = 95911.971711
    sData78.Close = 30366.16
    sData78.High = 32557.3
    sData78.Low = 29241.73
    sData78.Open = 32464.02
    sData78.Date = 1611705600.0
    securityDatas = append(securityDatas, sData78)
    sData79 := new(SecurityData)
    sData79.Volume = 92621.155617
    sData79.Close = 33364.87
    sData79.High = 33783.99
    sData79.Low = 29842.11
    sData79.Open = 30362.2
    sData79.Date = 1611792000.0
    securityDatas = append(securityDatas, sData79)
    sData80 := new(SecurityData)
    sData80.Volume = 193388.622446
    sData80.Close = 34252.21
    sData80.High = 38531.91
    sData80.Low = 31915.41
    sData80.Open = 33368.19
    sData80.Date = 1611878400.0
    securityDatas = append(securityDatas, sData80)
    sData81 := new(SecurityData)
    sData81.Volume = 82674.758249
    sData81.Close = 34262.89
    sData81.High = 34933.01
    sData81.Low = 32825.01
    sData81.Open = 34246.29
    sData81.Date = 1611964800.0
    securityDatas = append(securityDatas, sData81)
    sData82 := new(SecurityData)
    sData82.Volume = 66269.928016
    sData82.Close = 33092.99
    sData82.High = 34342.7
    sData82.Low = 32171.68
    sData82.Open = 34262.9
    sData82.Date = 1612051200.0
    securityDatas = append(securityDatas, sData82)
    sData83 := new(SecurityData)
    sData83.Volume = 80154.567802
    sData83.Close = 33526.38
    sData83.High = 34717.28
    sData83.Low = 32296.17
    sData83.Open = 33089.45
    sData83.Date = 1612137600.0
    securityDatas = append(securityDatas, sData83)
    sData84 := new(SecurityData)
    sData84.Volume = 78056.66988
    sData84.Close = 35466.25
    sData84.High = 35984.34
    sData84.Low = 33418.01
    sData84.Open = 33517.1
    sData84.Date = 1612224000.0
    securityDatas = append(securityDatas, sData84)
    sData85 := new(SecurityData)
    sData85.Volume = 80784.343663
    sData85.Close = 37618.88
    sData85.High = 37662.64
    sData85.Low = 35362.39
    sData85.Open = 35472.72
    sData85.Date = 1612310400.0
    securityDatas = append(securityDatas, sData85)
    sData86 := new(SecurityData)
    sData86.Volume = 89024.320756
    sData86.Close = 36936.67
    sData86.High = 38708.28
    sData86.Low = 36161.96
    sData86.Open = 37620.27
    sData86.Date = 1612396800.0
    securityDatas = append(securityDatas, sData86)
    sData87 := new(SecurityData)
    sData87.Volume = 65910.531514
    sData87.Close = 38290.25
    sData87.High = 38310.13
    sData87.Low = 36570.01
    sData87.Open = 36936.66
    sData87.Date = 1612483200.0
    securityDatas = append(securityDatas, sData87)
    sData88 := new(SecurityData)
    sData88.Volume = 94232.612846
    sData88.Close = 39186.95
    sData88.High = 40955.52
    sData88.Low = 38215.95
    sData88.Open = 38289.33
    sData88.Date = 1612569600.0
    securityDatas = append(securityDatas, sData88)
    sData89 := new(SecurityData)
    sData89.Volume = 81820.439177
    sData89.Close = 38795.7
    sData89.High = 39700.01
    sData89.Low = 37351.01
    sData89.Open = 39181.02
    sData89.Date = 1612656000.0
    securityDatas = append(securityDatas, sData89)
    sData90 := new(SecurityData)
    sData90.Volume = 121568.794672
    sData90.Close = 46374.88
    sData90.High = 46794.46
    sData90.Low = 37988.9
    sData90.Open = 38795.7
    sData90.Date = 1612742400.0
    securityDatas = append(securityDatas, sData90)
    sData91 := new(SecurityData)
    sData91.Volume = 114567.009318
    sData91.Close = 46420.43
    sData91.High = 48142.2
    sData91.Low = 44961.1
    sData91.Open = 46374.87
    sData91.Date = 1612828800.0
    securityDatas = append(securityDatas, sData91)
    sData92 := new(SecurityData)
    sData92.Volume = 78292.89657
    sData92.Close = 44807.59
    sData92.High = 47310.01
    sData92.Low = 43800.01
    sData92.Open = 46420.43
    sData92.Date = 1612915200.0
    securityDatas = append(securityDatas, sData92)
    sData93 := new(SecurityData)
    sData93.Volume = 81033.184776
    sData93.Close = 47969.52
    sData93.High = 48678.91
    sData93.Low = 43994.03
    sData93.Open = 44807.59
    sData93.Date = 1613001600.0
    securityDatas = append(securityDatas, sData93)
    sData94 := new(SecurityData)
    sData94.Volume = 81856.490636
    sData94.Close = 47287.61
    sData94.High = 48985.81
    sData94.Low = 46400.01
    sData94.Open = 47968.67
    sData94.Date = 1613088000.0
    securityDatas = append(securityDatas, sData94)
    sData95 := new(SecurityData)
    sData95.Volume = 58937.84066
    sData95.Close = 47153.7
    sData95.High = 48150.01
    sData95.Low = 46202.54
    sData95.Open = 47298.16
    sData95.Date = 1613174400.0
    securityDatas = append(securityDatas, sData95)
    sData96 := new(SecurityData)
    sData96.Volume = 70700.864117
    sData96.Close = 48577.8
    sData96.High = 49707.44
    sData96.Low = 47014.18
    sData96.Open = 47156.79
    sData96.Date = 1613260800.0
    securityDatas = append(securityDatas, sData96)
    sData97 := new(SecurityData)
    sData97.Volume = 63227.659425
    sData97.Close = 47911.11
    sData97.High = 49010.93
    sData97.Low = 46174.79
    sData97.Open = 48580.48
    sData97.Date = 1613347200.0
    securityDatas = append(securityDatas, sData97)
    sData98 := new(SecurityData)
    sData98.Volume = 78018.176005
    sData98.Close = 49133.46
    sData98.High = 50080.22
    sData98.Low = 47003.63
    sData98.Open = 47911.11
    sData98.Date = 1613433600.0
    securityDatas = append(securityDatas, sData98)
    sData99 := new(SecurityData)
    sData99.Volume = 84886.224046
    sData99.Close = 52119.72
    sData99.High = 52618.75
    sData99.Low = 48947.01
    sData99.Open = 49133.46
    sData99.Date = 1613520000.0
    securityDatas = append(securityDatas, sData99)
    sData100 := new(SecurityData)
    sData100.Volume = 58093.930825
    sData100.Close = 51552.61
    sData100.High = 52530.01
    sData100.Low = 50901.91
    sData100.Open = 52117.68
    sData100.Date = 1613606400.0
    securityDatas = append(securityDatas, sData100)
    return securityDatas
}

/*
* 图表的黑色风格
*/
func ChartToBlack(chart *FCView){
    inChart := chart.GetChart()
    chart.BackColor = "rgb(0,0,0)";
    chart.BorderColor = "rgb(100,100,100)";
    chart.TextColor = "rgb(255,255,255)";
    inChart.ScaleColor = "rgb(100,100,100)";
    inChart.CrossTipColor = "rgb(50,50,50)";
    inChart.CrossLineColor = "rgb(100,100,100)";
    inChart.GridColor = "rgba(100,100,100,125)";
    var indicatorColors[] string
    inChart.IndicatorColors = indicatorColors
    inChart.IndicatorColors = append(inChart.IndicatorColors, "rgb(255,255,255)")
    inChart.IndicatorColors = append(inChart.IndicatorColors, "rgb(255,255,0)")
    inChart.IndicatorColors = append(inChart.IndicatorColors, "rgb(255,0,255)")
    inChart.IndicatorColors = append(inChart.IndicatorColors, "rgb(255,0,0)")
    inChart.IndicatorColors = append(inChart.IndicatorColors, "rgb(0,255,255)")
    inChart.IndicatorColors = append(inChart.IndicatorColors, "rgb(0,255,0)")
    inChart.IndicatorColors = append(inChart.IndicatorColors, "rgb(255,255,0)")
    inChart.IndicatorColors = append(inChart.IndicatorColors, "rgb(255,255,255)")
}

var gPaint = CreatePaint()
var tChart = new(FCView)
 
func main() {
    gPaint.DefaultUIStyle = "dark"
    var canvas js.Value = js.
        Global().
        Get("document").
        Call("getElementById", "canvas")
    var context js.Value = canvas.Call("getContext", "2d")
    gPaint.Canvas = canvas
    gPaint.Context = context  
    var window js.Value = js.Global().Get("window")
    canvas.Set("width", window.Get("innerWidth").Float())
    canvas.Set("height", window.Get("innerHeight").Float())
    ScaleCanvas(gPaint)
    RegisterCanvas(gPaint)
    gPaint.OnPaint = OnPaint
    gPaint.OnPaintBorder = OnPaintBorder
    gPaint.OnMouseDown = OnMouseDown
    gPaint.OnMouseMove = OnMouseMove
    gPaint.OnMouseUp = OnMouseUp
    gPaint.OnMouseWheel = OnMouseWheel
    gPaint.OnClick = OnClick
    gPaint.OnUpdateView = UpdateView
    gPaint.OnMouseLeave = OnMouseLeave
    gPaint.OnMouseEnter = OnMouseEnter
    gPaint.OnTouchBegin = OnTouchBegin
    gPaint.OnTouchMove = OnTouchMove
    gPaint.OnTouchEnd = OnTouchEnd
    gPaint.IsMobile = false
    mode := 1
    if mode == 0{
        xmlStr := `<?xml version="1.0" encoding="utf-8"?>
        <html xmlns="facecat">
          <head>
          </head>
          <body>
            <div dock="fill" type="tab" selectedindex="0" name="TabView">
              <div name="TabPage" text="可视化生成" type="tabpage">
                <chart size="200,200" name="Chart" text="Chart" location="212,164" dock="Fill">
                </chart>
              </div>
              <div name="TabPage2" text="指标" type="tabpage" />
              <div name="TabPage3" text="画线" type="tabpage" />
            </div>
          </body>
        </html>`;
        RenderFaceCat(gPaint, xmlStr)
        chart := FindViewByName("Chart", gPaint.Views)
        inChart := chart.GetChart()
        ChartToBlack(chart)
        tChart = chart
        tabPage2 := FindViewByName("TabPage2", gPaint.Views)
        tabPage3 := FindViewByName("TabPage3", gPaint.Views)
        inChart.RightVScaleWidth = 60
        chart.Location = CreatePoint(0, 0)
        inChart.Data = getSecurityDatas()
        inChart.MainIndicator = "BOLL" //主图指标
        inChart.ShowIndicator = "MACD" //显示指标
        ResetChartVisibleRecord(chart)
        CheckChartLastVisibleIndex(chart)
        CalcChartIndicator(chart)
        indLayout := CreateView("layout")
        indLayout.Dock = "fill"
        indLayout.BackColor = "rgb(0,0,0)"
        indLayout.Location = CreatePoint(0, 0)
        indLayout.Size = CreateSize(tabPage2.Size.Cx, tabPage2.Size.Cy)
        indLayout.GetLayoutDiv().AutoWrap = true
        AddViewToParent(indLayout, tabPage2)
        var indicators []string
        indicators = append(indicators, "MA")
        indicators = append(indicators, "BOLL")
        indicators = append(indicators, "MACD")
        indicators = append(indicators, "KDJ")
        indicators = append(indicators, "BIAS")
        indicators = append(indicators, "BBI")
        indicators = append(indicators, "RSI")
        indicators = append(indicators, "ROC")
        indicators = append(indicators, "WR")
        indicators = append(indicators, "DMA")
        indicators = append(indicators, "TRIX")
        indicators = append(indicators, "CCI")
        for i := 0; i < len(indicators); i++{
            button := CreateView("button")
            button.Text = indicators[i]
            button.ViewName = "Indicator"
            button.Size = CreateSize(100, 50)
            button.Margin = CreatePadding(10, 10, 10, 10)
            button.TextColor = "rgb(255,255,255)"
            button.BackColor = "rgb(0,0,0)"
            button.BorderColor = "rgb(100,100,100)"
            AddViewToParent(button, indLayout)
        }    

        indLayout2 := CreateView("layout")
        indLayout2.Dock = "fill"
        indLayout2.BackColor = "rgb(0,0,0)"
        indLayout2.Location = CreatePoint(0, 0)
        indLayout2.Size = CreateSize(tabPage3.Size.Cx, tabPage3.Size.Cy)
        indLayout2.GetLayoutDiv().AutoWrap = true
        AddViewToParent(indLayout2, tabPage3)

        var plots []string
        plots = append(plots, "Line")
        plots = append(plots, "Segment")
        plots = append(plots, "Ray")
        plots = append(plots, "Triangle")
        plots = append(plots, "Rect")
        plots = append(plots, "Cycle")
        plots = append(plots, "CircumCycle")
        plots = append(plots, "Ellipse")
        plots = append(plots, "AngleLine")
        plots = append(plots, "LRLine")
        plots = append(plots, "LRChannel")
        plots = append(plots, "SymmetricTriangle")
        plots = append(plots, "LRBand")
        plots = append(plots, "ParalleGram")
        plots = append(plots, "SpeedResist")
        plots = append(plots, "FiboFanline")
        plots = append(plots, "FiboTimezone")
        plots = append(plots, "Percent")
        plots = append(plots, "BoxLine")
        plots = append(plots, "TironeLevels")
        plots = append(plots, "QuadrantLines")
        plots = append(plots, "Parallel")
        plots = append(plots, "GoldenRatio")
        plots = append(plots, "ArrowSegment")
        for i:= 0; i < len(plots); i++{
            button := CreateView("button")
            button.Text = plots[i]
            button.ViewName = "Plot"
            button.Size = CreateSize(100, 50)
            button.Margin = CreatePadding(10, 10, 10, 10)
            button.TextColor = "rgb(255,255,255)"
            button.BackColor = "rgb(0,0,0)"
            button.BorderColor = "rgb(100,100,100)"
            AddViewToParent(button, indLayout2)
        }
        UpdateViewDefault(gPaint.Views)
        Invalidate(gPaint)
    }else{
        xmlStr := `<?xml version="1.0" encoding="utf-8"?>
        <html xmlns="facecat">
          <head>
          </head>
          <body>
            <div type="splitlayout" name="divAll" candragsplitter="true" layoutstyle="toptobottom" dock="fill" size="400,505" splitterposition="0,80,400,80" bordercolor="none">
              <div type="tab" name="tabTradeAccount" bordercolor="none" backcolor="none">
                <div type="tabpage" name="pageTradeAccount" text="持仓" headersize="100,0" backcolor="none" bordercolor="none" padding="5,5,5,5">
                  <table name="gridTradeAccount" dock="fill" headerheight="70" showhscrollbar="false" bordercolor="none" backcolor="-200000000163">
                    <tr>
                      <th name="colF1" text="静态权益" width="120" location="0,0" size="120,70" />
                      <th name="colF2" text="平仓盈亏" width="120" />
                      <th name="colF3" text="浮动盈亏" width="120" />
                      <th name="colF4" text="持仓盈亏" width="120" location="240,0" size="120,70" />
                      <th name="colF5" text="动态权益" width="120" />
                      <th name="colF6" text="占用保证金" width="120" />
                      <th name="colF7" text="下单冻结" width="120" />
                      <th name="colF8" text="可用资金" width="120" />
                      <th name="colF9" text="风险度" width="120" />
                      <th name="colF10" text="冻结保证金" width="120" />
                      <th name="colF11" text="冻结手续费" width="120" />
                      <th name="colF12" text="手续费" width="120" />
                      <th name="colF13" text="上次结算准备金" width="120" />
                      <th name="colF14" text="上次信用额度" width="120" />
                      <th name="colF15" text="上次质押金额" width="120" />
                      <th name="colF16" text="质押金额" width="120" />
                      <th name="colF17" text="今日出金" width="120" />
                      <th name="colF18" text="今日入金" width="120" />
                      <th name="colF19" text="信用金额" width="120" />
                      <th name="colF20" text="保底资金" width="120" />
                      <th name="colF21" text="可取资金" width="120" />
                    </tr>
                  </table>
                </div>
              </div>
              <div type="splitlayout" name="divBottom" candragsplitter="true" layoutstyle="bottomtotop" size="400,450" splitterposition="0,430,400,430" bordercolor="none" backcolor="none">
                <div name="divStatus" size="966,17">
                  <label name="lblTradingTime" text="--" location="3,2" size="100,20" font="Default,12" />
                  <label name="lbllog" text="--" location="105,2" size="352,20" font="Default,12" />
                </div>
                <div type="splitlayout" name="divMiddle" candragsplitter="true" layoutstyle="toptobottom" size="600,600" splitmode="percentsize" splitterposition="0,450,400,450" bordercolor="none" backcolor="none">
                  <div type="splitlayout" name="divMiddleTop" candragsplitter="true" layoutstyle="bottomtotop" size="600,600" splitterposition="0,330,400,330" bordercolor="none" backcolor="none">
                    <div bordercolor="none" padding="5,5,5,5" backcolor="none">
                      <div type="splitlayout" name="divMain" dock="fill" candragsplitter="true" layoutstyle="lefttoright" size="420,420" splitterposition="310,0,310,300" bordercolor="none" backcolor="none">
                        <div bordercolor="none" backcolor="none" padding="0,0,5,0">
                          <div type="tab" name="tabTradeMain" selectedindex="0" location="0,0" size="1166,270" dock="fill" backcolor="-200000000163">
                            <div type="tabpage" name="pageTrade" text="标准下单" backcolor="none" bordercolor="none">
                              <div name="divTrade" size="310,250" dock="fill" location="0,0" bordercolor="none" backcolor="Back">
                                <label name="lblContract" text="合约" location="8,18" size="37,20" font="Default,14" />
                                <label name="lblBuySell" text="买卖" location="8,49" size="38,19" font="Default,14" />
                                <input type="custom" cid="button" text="自动" location="3,76" size="46,20" />
                                <label name="lblVolume" text="手数" location="8,109" size="38,19" font="Default,14" />
                                <input type="radio" name="rbOpen" backcolor="rgba(43,138,195,100)" checked="true" text="开仓" location="52,76" size="65,20" groupname="OpenClose" />
                                <input type="radio" name="rbCloseToday" text="平今" location="120,76" size="65,20" groupname="OpenClose" />
                                <input type="radio" name="rbClose" text="平仓" location="182,76" size="65,20" groupname="OpenClose" />
                                <input type="radio" name="rbBuy" backcolor="rgba(255,0,0,100)" checked="true" text="买入" location="53,47" size="64,20" groupname="BuySell" />
                                <input type="radio" name="rbSell" text="卖出" location="119,47" size="64,20" groupname="BuySell" />
                                <input type="text" name="txtIssueCode" font="Default,20" location="53,11" size="163,28" lineheight="28" multiline="false" />
                                <input type="checkbox" name="cbLock" text="锁定" location="220,15" size="73,20" canfocus="false" buttonsize="16,16" />
                                <input type="range" name="spinVolume" font="Default,20" digit="0" location="52,102" size="115,28" lineheight="28" maximum="100000000" minimum="1" textalign="far" />
                                <input type="range" name="spinPrice" digit="2" font="Default,20" location="52,142" size="115,24" lineheight="28" maximum="100000000" textalign="far" />
                                <input type="button" name="btnOrder" font="Default,16" text="下单" cursor="pointer" backcolor="rgb(15,193,118)" location="8,179" size="211,48" />
                                <input type="button" name="btnCancel" text="取消" location="226,184" backcolor="rgb(248,73,96)" size="74,24" font="Default,12" />
                                <input type="button" name="btnPreCondition" text="预埋/条件" location="226,209" size="74,23" font="Default,12" />
                                <label name="lblLess" text="&lt;=" location="185,104" size="26,21" font="Default,16" />
                                <label name="lblMaxVolume" text="0" location="206,104" size="16,21" font="Default,16" />
                                <label name="lblUp" text="0" location="188,121" size="100,20" opacity="1" />
                                <label name="lblAskPrice" text="0" location="188,135" size="53,20" />
                                <label name="lblBidPrice" text="0" location="188,149" size="51,21" />
                                <label name="lblDown" text="0" location="188,163" size="48,20" />
                                <label name="Label" text="/" location="241,136" size="17,20" font="Default,12" />
                                <label name="Label1" text="/" location="239,150" size="16,20" font="Default,12" />
                                <label name="lblAskVolume" text="0" location="250,136" size="57,18" />
                                <label name="lblBidVolume" text="0" location="250,150" size="57,20" />
                                <input type="button" name="btnTradeMode" text="跟盘" location="3,143" size="46,20" />
                              </div>
                            </div>
                          </div>
                        </div>
                        <div type="splitlayout" name="divMain" dock="fill" candragsplitter="true" layoutstyle="righttoleft" size="420,420" splitterposition="100,0" bordercolor="none" backcolor="none">
                          <div bordercolor="none" backcolor="none" padding="5,0,0,0">
                            <div type="tab" name="tabOrder2" selectedindex="1" backcolor="-200000000163" dock="fill">
                              <div type="tabpage" name="pageChart" text="图形" bordercolor="none" backcolor="none">
                                <chart name="chart" dock="fill" />
                              </div>
                            </div>
                          </div>
                          <div type="tab" name="tabOrder" selectedindex="1" backcolor="-200000000163">
                            <div type="tabpage" name="pageAllOrders" text="所有委托单" backcolor="none" bordercolor="none">
                              <div type="splitlayout" name="divOrder" dock="fill" layoutstyle="bottomtotop" size="400,400" splitterposition="0,370,400,370" backcolor="none" bordercolor="none">
                                <div name="divDealRecordType" backcolor="none" bordercolor="none">
                                  <input type="radio" name="rdAllOrders" groupname="allOrders" checked="true" location="0,6" text="全部单" size="100,20" />
                                  <input type="radio" name="rdOrder" groupname="allOrders" location="100,6" text="挂单" size="100,20" />
                                  <input type="radio" name="rdDeal" groupname="allOrders" location="200,6" text="已成交" size="100,20" />
                                  <input type="radio" name="rdCancel" groupname="allOrders" location="300,6" text="已撤单/错单" size="120,20" />
                                  <input type="button" name="btnCancelOrder2" location="450,2" size="100,26" text="撤单" />
                                  <input type="button" name="btnCancelAllOrder2" location="570,2" size="100,26" text="全撤" />
                                </div>
                                <table name="gridOrder" dock="Fill" size="569,330" backcolor="none" bordercolor="none">
                                  <tr>
                                    <th name="colA1" columntype="text" text="报单编号" width="80" />
                                    <th name="colA2" columntype="text" text="合约" width="80" />
                                    <th name="colA3" columntype="text" horizontalalign="center" text="买卖" width="60" />
                                    <th name="colA4" columntype="text" horizontalalign="center" text="开平" width="60" />
                                    <th name="colA5" columntype="text" horizontalalign="center" text="挂单状态" width="140" />
                                    <th name="colA6" columntype="double" horizontalalign="far" text="报单价格" width="80" />
                                    <th name="colA7" columntype="int" horizontalalign="far" text="报单手数" width="80" />
                                    <th name="colA8" columntype="int" horizontalalign="far" text="未成交手数" width="80" />
                                    <th name="colA9" columntype="int" horizontalalign="far" text="成交手数" width="80" />
                                    <th name="colA10" columntype="text" horizontalalign="center" text="报单时间" width="60" />
                                    <th name="colA11" columntype="text" horizontalalign="center" text="最后成交时间" width="80" />
                                    <th name="colA12" columntype="double" horizontalalign="far" text="成交均价" width="80" />
                                    <th name="colA13" columntype="double" horizontalalign="far" text="冻结保证金" width="80" />
                                    <th name="colA14" columntype="double" horizontalalign="far" text="冻结手续费" width="80" />
                                    <th name="colA15" columntype="text" horizontalalign="center" text="投保" width="60" />
                                    <th name="colA16" columntype="text" text="交易所" width="80" />
                                    <th name="colA18" columntype="text" horizontalalign="center" text="报单价格条件" width="100" />
                                    <th name="colA19" columntype="text" text="有效期类型" width="200" />
                                    <th name="colA20" columntype="text" horizontalalign="center" text="报单类型" width="60" />
                                    <th name="colA21" columntype="text" horizontalalign="center" text="是否强平" width="80" />
                                    <th name="colA22" columntype="text" horizontalalign="center" text="强平原因" width="80" />
                                    <th name="colA23" columntype="text" text="指令结果" width="80" />
                                    <th name="colA24" columntype="text" text="客户端信息" width="80" />
                                    <th name="colA25" columntype="text" text="撤单锁定" width="60" />
                                  </tr>
                                </table>
                              </div>
                            </div>
                            <div type="tabpage" name="pageTradeRecord" text="成交记录" backcolor="none" bordercolor="none">
                              <div type="splitlayout" name="divTradeRecord" dock="fill" layoutstyle="bottomtotop" size="400,400" splitterposition="0,370,400,370" backcolor="none" bordercolor="none">
                                <div name="divTradeRecordType" backcolor="none" bordercolor="none">
                                  <input type="radio" name="rdDetail" groupname="tradeRecordType" checked="true" location="0,5" text="明细" size="100,20" />
                                  <input type="radio" name="rdSummary" groupname="tradeRecordType" location="100,5" text="合计" size="100,20" />
                                </div>
                                <div name="divTradeRecordInner" backcolor="none" bordercolor="none">
                                  <table name="gridTradeRecord" dock="fill" backcolor="none" bordercolor="none">
                                    <tr>
                                      <th name="colR1" columntype="text" text="成交编号" width="80" />
                                      <th name="colR2" columntype="text" text="合约" width="80" />
                                      <th name="colR3" columntype="text" horizontalalign="center" text="买卖" width="60" />
                                      <th name="colR4" columntype="text" horizontalalign="center" text="开平" width="60" />
                                      <th name="colR5" columntype="double" horizontalalign="far" text="成交价格" width="80" />
                                      <th name="colR6" columntype="int" horizontalalign="far" text="成交手数" width="80" />
                                      <th name="colR7" columntype="text" horizontalalign="center" text="成交时间" width="80" />
                                      <th name="colR8" columntype="text" horizontalalign="center" text="报单编号" width="80" />
                                      <th name="colR9" columntype="text" horizontalalign="center" text="成交类型" width="80" />
                                      <th name="colR10" columntype="text" horizontalalign="center" text="投保" width="60" />
                                      <th name="colR11" columntype="text" text="交易所" width="80" />
                                      <th name="colR12" columntype="double" horizontalalign="far" text="手续费" width="80" />
                                    </tr>
                                  </table>
                                  <table name="gridTradeStatistics" dock="fill" visible="false" backcolor="none" bordercolor="none">
                                    <tr>
                                      <th name="colS1" columntype="text" text="合约" width="80" />
                                      <th name="colS2" columntype="text" text="交易所" width="80" />
                                      <th name="colS3" columntype="text" horizontalalign="center" text="买卖" width="80" />
                                      <th name="colS4" columntype="text" horizontalalign="center" text="开平" width="80" />
                                      <th name="colS5" columntype="double" horizontalalign="far" text="成交均价" width="100" />
                                      <th name="colS6" columntype="int" horizontalalign="far" text="成交手数" width="100" />
                                      <th name="colS7" columntype="double" horizontalalign="far" text="手续费" width="100" />
                                      <th name="colS8" columntype="text" horizontalalign="center" text="投保" width="60" />
                                    </tr>
                                  </table>
                                </div>
                              </div>
                            </div>
                          </div>
                        </div>
                      </div>
                    </div>
                    <div bordercolor="none" backcolor="none" padding="5,5,5,5">
                      <div type="tab" name="tabQuote" selectedindex="0" size="400,400" backcolor="-200000000163" dock="fill">
                        <div type="tabpage" name="pagePageQuote" text="报价表" bordercolor="none" backcolor="none">
                          <table name="gridLatestData" dock="fill" location="0,0" size="914,160" bordercolor="none" backcolor="none">
                            <tr>
                              <th name="colQ1" columntype="text" text="合约" width="80" />
                              <th name="colQ2" columntype="text" text="合约名" width="100" />
                              <th name="colQ3" columntype="double" horizontalalign="far" text="最新价" width="60" />
                              <th name="colQ4" columntype="double" horizontalalign="far" text="涨跌" width="60" />
                              <th name="colQ5" columntype="double" horizontalalign="far" text="买价" width="60" location="300,0" size="60,20" />
                              <th name="colQ6" columntype="int" horizontalalign="far" text="买量" width="60" location="360,0" size="60,20" />
                              <th name="colQ7" columntype="double" horizontalalign="far" text="卖价" width="60" />
                              <th name="colQ8" columntype="int" horizontalalign="far" text="卖量" width="60" />
                              <th name="colQ9" columntype="int" horizontalalign="far" text="成交量" width="60" />
                              <th name="colQ10" columntype="int" horizontalalign="far" text="持仓量" width="60" />
                              <th name="colQ11" columntype="double" horizontalalign="far" text="涨停价" width="60" />
                              <th name="colQ12" columntype="double" horizontalalign="far" text="涨停价" width="60" />
                              <th name="colQ13" columntype="double" horizontalalign="far" text="今开盘" width="60" />
                              <th name="colQ14" columntype="double" horizontalalign="far" text="昨结算" width="60" />
                              <th name="colQ15" columntype="double" horizontalalign="far" text="最高价" width="60" />
                              <th name="colQ16" columntype="double" horizontalalign="far" text="最低价" width="60" />
                              <th name="colQ17" columntype="int" horizontalalign="far" text="现量" width="60" />
                              <th name="colQ18" columntype="percent" horizontalalign="far" text="涨跌幅" width="60" />
                              <th name="colQ19" columntype="double" horizontalalign="far" text="昨收盘" width="60" />
                              <th name="colQ20" columntype="thousands" horizontalalign="far" text="成交额" width="100" />
                              <th name="colQ21" columntype="text" text="交易所" width="60" />
                              <th name="colQ22" columntype="text" horizontalalign="center" text="行情更新时间" width="100" />
                              <th name="colQ23" columntype="double" text="昨持仓量" width="60" />
                              <th name="colQ24" columntype="double" text="今收盘" width="60" />
                              <th name="colQ25" columntype="double" text="结算价" width="60" />
                              <th name="colQ26" columntype="double" text="当日均价" width="80" />
                              <th name="colQ27" columntype="int" text="持仓增减" width="80" />
                              <th name="colQ28" columntype="double" text="组合买价" width="80" />
                              <th name="colQ29" columntype="int" text="组合买量" width="80" />
                              <th name="colQ30" columntype="double" text="组合卖价" width="80" />
                              <th name="colQ31" columntype="int" text="组合卖量" width="80" />
                              <th name="colQ32" columntype="int" text="撤单次数" width="80" />
                            </tr>
                          </table>
                        </div>
                        <div type="tabpage" name="pageContracts" text="合约列表" bordercolor="none" backcolor="none">
                          <table name="gridContracts" dock="fill" bordercolor="none" backcolor="none">
                            <tr>
                              <th name="colC1" columntype="text" text="品种代码" width="80" />
                              <th name="colC2" columntype="text" text="合约" width="60" />
                              <th name="colC3" columntype="text" text="合约名" width="100" />
                              <th name="colC4" columntype="text" text="交易所" width="60" />
                              <th name="colC5" columntype="int" horizontalalign="far" text="合约乘数" width="100" />
                              <th name="colC6" columntype="double" horizontalalign="far" text="最小价格变动单位" width="100" />
                              <th name="colC7" columntype="text" horizontalalign="center" text="品种类型" width="100" />
                              <th name="colC8" columntype="text" horizontalalign="center" text="最后日期" width="100" />
                              <th name="colC9" columntype="percent" horizontalalign="far" text="多头保证金率" width="100" />
                              <th name="colC10" columntype="percent" horizontalalign="far" text="空头保证金率" width="100" />
                              <th name="colC11" columntype="double" horizontalalign="far" text="开仓手续费" width="100" />
                              <th name="colC12" columntype="double" horizontalalign="far" text="平仓手续费" width="100" />
                              <th name="colC13" columntype="double" horizontalalign="far" text="平今手续费" width="100" />
                              <th name="colC14" columntype="percent" horizontalalign="far" text="开仓手续费率" width="100" />
                              <th name="colC15" columntype="percent" horizontalalign="far" text="平仓手续费率" width="100" />
                              <th name="colC16" columntype="percent" horizontalalign="far" text="平今手续费率" width="100" />
                              <th name="colC17" columntype="int" horizontalalign="far" text="市价单最大下单量" width="100" />
                              <th name="colC18" columntype="int" horizontalalign="far" text="限价单最大下单量" width="100" />
                            </tr>
                          </table>
                        </div>
                      </div>
                    </div>
                  </div>
                  <div bordercolor="none" padding="5,5,5,5" backcolor="-200000000163">
                    <div type="tab" name="tabInvestorPosition" selectedindex="0" dock="fill" backcolor="none">
                      <div type="tabpage" name="pagePageInvestorPosition" text="持仓" bordercolor="none" backcolor="none">
                        <div type="splitlayout" name="divInvestorPosition" dock="fill" layoutstyle="bottomtotop" size="400,400" splitterposition="0,370,400,370" bordercolor="none" backcolor="none">
                          <div name="divInvestorPositionBottom" bordercolor="none" backcolor="none">
                            <input type="radio" name="cbInvestorPosition" checked="true" location="5,5" groupname="InvestorPosition" size="80,20" text="持仓" />
                            <input type="radio" name="cbInvestorPositionDetail" groupname="InvestorPosition" location="80,5" size="80,20" text="持仓明细" />
                            <input type="radio" name="cbCompPosition" groupname="InvestorPosition" location="180,3" size="80,23" text="组合持仓" visible="false" />
                            <input type="button" name="btnOpenInterestIP" location="300,3" size="80,23" text="对价平仓" height="24" />
                            <input type="button" name="btnMarketPositionIP" location="390,3" size="80,23" text="市价平仓" height="24" />
                            <input type="button" name="btnMarketBackhandIP" location="480,3" size="80,23" text="市价反手" height="24" />
                          </div>
                          <div name="divInvestorPositionTop" bordercolor="none" backcolor="none">
                            <table name="gridInvestorPosition" dock="fill" bordercolor="none" backcolor="none">
                              <tr>
                                <th name="colP1" columntype="text" text="合约" width="80" />
                                <th name="colP2" columntype="text" horizontalalign="center" text="多空" width="60" />
                                <th name="colP3" columntype="int" horizontalalign="far" text="总持仓" width="60" />
                                <th name="colP4" columntype="int" horizontalalign="far" text="昨仓" width="60" />
                                <th name="colP5" columntype="int" horizontalalign="far" text="今仓" width="60" />
                                <th name="colP6" columntype="int" horizontalalign="far" text="可平量" width="60" />
                                <th name="colP7" columntype="double" horizontalalign="far" text="持仓均价" width="80" />
                                <th name="colP8" columntype="thousands" horizontalalign="far" text="持仓盈亏" width="100" />
                                <th name="colP9" columntype="thousands" horizontalalign="far" text="占用保证金" width="100" />
                                <th name="colP10" columntype="text" horizontalalign="center" text="投保" width="60" />
                                <th name="col111" columntype="text" text="交易所" width="80" />
                                <th name="colP12" columntype="int" horizontalalign="far" text="总多仓" width="60" />
                                <th name="colP13" columntype="int" horizontalalign="far" text="总空仓" width="60" />
                                <th name="colP14" columntype="int" horizontalalign="far" text="今多仓" width="60" />
                                <th name="colP15" columntype="int" horizontalalign="far" text="今空仓" width="60" />
                                <th name="colP16" columntype="int" horizontalalign="far" text="总可平今量" width="100" />
                                <th name="colP17" columntype="int" horizontalalign="far" text="总可平仓量" width="100" />
                                <th name="colP18" columntype="int" horizontalalign="far" text="平今挂单量" width="100" />
                                <th name="colP19" columntype="int" horizontalalign="far" text="平仓挂单量" width="100" />
                                <th name="colP20" columntype="int" horizontalalign="far" text="组合冻结量" width="100" />
                                <th name="colP21" columntype="int" horizontalalign="far" text="可平今量" width="80" />
                                <th name="col122" columntype="int" horizontalalign="far" text="可平仓量" width="80" />
                                <th name="colP23" columntype="double" horizontalalign="far" text="开仓均价" width="100" />
                                <th name="colP24" columntype="double" horizontalalign="far" text="多头开仓价" width="100" />
                                <th name="colP25" columntype="double" horizontalalign="far" text="空头开仓价" width="100" />
                                <th name="colP26" columntype="thousands" horizontalalign="far" text="浮动盈亏" width="100" />
                                <th name="colP27" columntype="thousands" horizontalalign="far" text="总盈亏" width="80" />
                                <th name="colP28" columntype="int" horizontalalign="far" text="今开仓量" width="80" />
                                <th name="colP29" columntype="int" horizontalalign="far" text="今平仓量" width="80" />
                                <th name="colP30" columntype="double" horizontalalign="far" text="现价" width="80" />
                                <th name="colP31" columntype="double" horizontalalign="far" text="最新差价" width="80" />
                              </tr>
                            </table>
                            <table name="gridInvestorPositionDetail" dock="fill" visible="false" bordercolor="none" backcolor="none">
                              <tr>
                                <th name="colT1" columntype="text" text="成交编号" width="80" />
                                <th name="colT2" columntype="text" text="合约" width="80" />
                                <th name="colT3" columntype="text" horizontalalign="center" text="多空" width="60" />
                                <th name="colT4" columntype="int" horizontalalign="far" text="手数" width="60" />
                                <th name="colT5" columntype="double" horizontalalign="far" text="开仓价" width="80" />
                                <th name="colT6" columntype="thousands" horizontalalign="far" text="占用保证金" width="100" />
                                <th name="colT7" columntype="text" text="持仓类型" width="80" />
                                <th name="colT8" columntype="text" horizontalalign="center" text="投保" width="60" />
                                <th name="colT9" columntype="text" horizontalalign="center" text="开仓时间" width="100" />
                                <th name="colT10" columntype="thousands" horizontalalign="far" text="持仓盈亏" width="100" />
                                <th name="colT11" columntype="thousands" horizontalalign="far" text="平仓盈亏" width="100" />
                                <th name="colT12" columntype="text" text="交易所" width="80" />
                                <th name="colT13" columntype="text" text="组合状态" width="100" />
                                <th name="colT14" columntype="double" horizontalalign="far" text="昨结算" width="80" />
                                <th name="colT15" columntype="int" horizontalalign="far" text="平仓量" width="80" />
                                <th name="colT16" columntype="thousands" horizontalalign="far" text="浮动盈亏" width="100" />
                                <th name="colT17" columntype="double" horizontalalign="far" text="最新价" width="80" />
                                <th name="colT18" columntype="int" horizontalalign="far" text="组合合约代码" width="100" />
                              </tr>
                            </table>
                            <table name="gridInvestorCombinePositionDetail" dock="fill" visible="false" bordercolor="none" backcolor="none">
                              <tr>
                                <th name="colM1" columntype="text" text="合约" width="120" />
                                <th name="colM2" columntype="text" horizontalalign="center" text="买卖" width="60" />
                                <th name="colM3" columntype="int" horizontalalign="far" text="手数" width="60" />
                                <th name="colM4" columntype="double" horizontalalign="far" text="开仓均价" width="100" />
                                <th name="colM5" columntype="text" horizontalalign="center" text="投保" width="60" />
                              </tr>
                            </table>
                          </div>
                        </div>
                      </div>
                    </div>
                  </div>
                </div>
              </div>
            </div>
          </body>
        </html>`
        RenderFaceCat(gPaint, xmlStr)
    }
    for {
        select {}
    }
}
